From 31b71b8284a2014baa031c88ea9943f295002220 Mon Sep 17 00:00:00 2001 From: Darkhan Nausharipov Date: Tue, 28 Mar 2023 16:13:21 +0600 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 95c82ec5be90e64f8e62072d4b7742db77b0558f Merge: 7066061152 c796d856f7 Author: Darkhan Nausharipov <31556582+nausharipov@users.noreply.github.com> Date: Tue Mar 28 16:07:43 2023 +0600 Merge pull request #441 from akvelon/issue25283-tobf-sucfuu [ToB] [Frontend] Save code for unauthenticated users commit c796d856f74dfb3d3371c9421e2c09eb4a5196a8 Author: darkhan.nausharipov Date: Tue Mar 28 16:05:08 2023 +0600 _isSnippetTypeSavable (#25283) commit 7b487a0b4c2fd83512bc2da53bf403d60520ae3d Author: darkhan.nausharipov Date: Tue Mar 28 15:49:29 2023 +0600 disabled saving solution code (#25283) commit be3e3460527263146eb13c440056d553ae867938 Author: Alexey Inkin Date: Tue Mar 28 13:22:05 2023 +0400 Improve comments, remove unused code (#25283) commit 3434381ed159e646949e5e736a491b95e0cad66d Author: darkhan.nausharipov Date: Mon Mar 27 20:28:39 2023 +0600 getSavedDescriptor (#25283) commit 7dbb6b44dd7dcb5e0835f62d4d9454b4c5cb7c9a Author: darkhan.nausharipov Date: Mon Mar 27 20:28:07 2023 +0600 _getStandardOrEmptyDescriptor (#25283) commit b9d76e61660b4180efed79cfb19470aad84e7e00 Author: darkhan.nausharipov Date: Mon Mar 27 18:19:49 2023 +0600 comments (#25283) commit cc7ff54d6c231285dc38eb048da753cb7ddf59a8 Merge: 8410493f38 7066061152 Author: darkhan.nausharipov Date: Fri Mar 24 21:23:19 2023 +0600 Merge branch 'issue24538-save-user-code' into issue25283-tobf-sucfuu commit 8410493f388ab91f42bb04c26a087331dc25f2e5 Author: darkhan.nausharipov Date: Fri Mar 24 20:37:49 2023 +0600 comments (#25283) commit 7066061152a1415297be5b1fb4729a3322b9676f Merge: 879795b632 ddae966f33 Author: darkhan.nausharipov Date: Fri Mar 24 20:03:34 2023 +0600 Merge branch 'master' into issue24538-save-user-code commit 8575c6e8f1f4a837c62403e941cf31e1511cf290 Author: darkhan.nausharipov Date: Fri Mar 24 12:33:28 2023 +0600 addressing comments (#25283) commit 172f18f33dc5648e0d5a6105430a10e2baaca8fb Author: darkhan.nausharipov Date: Mon Mar 20 19:26:20 2023 +0600 comment fixes (#25283) commit 099b0f19955dc119e0de53a098d424d4cf2d6ad3 Author: darkhan.nausharipov Date: Fri Mar 17 13:28:42 2023 +0600 changes for demo (#25283) commit 426d43ee066b02816ceef4deab62f96ee855fdc8 Author: darkhan.nausharipov Date: Wed Mar 15 21:42:15 2023 +0600 untested multi-file saving (#25283) commit 879795b632f5863ae9f477c30f40cb18164cb205 Merge: 1521ab9d93 04c2de61e5 Author: darkhan.nausharipov Date: Tue Mar 14 20:39:29 2023 +0600 Merge branch 'master' into issue24538-save-user-code commit 8c7807bbb47906cfc4d68c6a30dc740325688bf5 Author: darkhan.nausharipov Date: Thu Mar 2 20:24:01 2023 +0600 setUnit & HiveLocalStorageCache (#25283) commit 6b54331285e912d3e989ffcc6d7a5c446616ea2f Author: darkhan.nausharipov Date: Tue Feb 28 18:32:03 2023 +0600 unfinished ContentExampleLoadingDescriptor (#25283) commit 20e097ef00ab04cc25c4fca0598de4d4cd6a7b9a Author: darkhan.nausharipov Date: Mon Feb 27 12:03:59 2023 +0600 deleted google_sign_in from pubspec (#25283) commit bdf6f4948f9a9a8624f2c4417dd9645b6e188f7e Merge: f755775829 1521ab9d93 Author: darkhan.nausharipov Date: Mon Feb 27 12:01:19 2023 +0600 Merge branch 'issue24538-save-user-code' into issue25283-tobf-sucfuu commit 1521ab9d93f1ea1d964a58ac0f7b87213702cd01 Author: darkhan.nausharipov Date: Thu Feb 23 19:36:50 2023 +0600 CodeBlock widget (#25529) commit b638355e33cfbc1cd73e8ccaf7b8b65dfa6c7184 Author: darkhan.nausharipov Date: Thu Feb 23 19:34:00 2023 +0600 added missing notifyListeners (#24538) commit 5d22b4cda7a944cbbd650e6673ed55d63f4b5dc1 Author: darkhan.nausharipov Date: Thu Feb 23 19:33:01 2023 +0600 scrollbar in markdown code block (#25529) commit f7557758290b48fda83b8abaf6487bce36ea6c5e Author: darkhan.nausharipov Date: Wed Feb 22 11:37:58 2023 +0600 resolve deprecation warnings todo (#25283) commit 56264acd2da1a565f3dbb98dab1a41dff54ef54b Author: darkhan.nausharipov Date: Wed Feb 22 11:30:22 2023 +0600 flutter v3.7 support (#24538) commit 08989ab7e0a8bf7623aff19de10e22b38ecb20dd Merge: 9e3666c706 40838f7644 Author: darkhan.nausharipov Date: Wed Feb 22 11:00:47 2023 +0600 Merge branch 'master' into issue24538-save-user-code commit 6860d1b367e739abc73e35e48774869ae016872f Author: darkhan.nausharipov Date: Mon Feb 20 11:39:36 2023 +0600 Flutter v3.7.3 support for ToB (#25283) commit 9e3666c706ff3bc6a3a02ccaf33738a116820502 Author: darkhan.nausharipov Date: Wed Feb 8 17:29:53 2023 +0600 set sdkId to fix a bug (#24538) commit 5381d9e0c10d29e2e605c941d0b74d0db16a7b27 Author: darkhan.nausharipov Date: Mon Feb 6 13:37:00 2023 +0600 _Buttons padding (#24538) commit 4a419a611c8e7e28e178fb0488bd308d6c52add8 Author: darkhan.nausharipov Date: Mon Feb 6 11:26:47 2023 +0600 moved hints to the left (#24538) commit 5637c4171a65ccb4a87019b492245b8cdaec38a5 Author: darkhan.nausharipov Date: Mon Feb 6 11:22:07 2023 +0600 scrollable hints (#24538) commit c7c51b1234b87fe374bce6f9b7dc27d299605b00 Author: darkhan.nausharipov Date: Mon Feb 6 11:00:15 2023 +0600 commit to relaunch RAT check (#24538) commit 8eed5d3174fdf193b9a4c62631e3687c2c505d6f Author: darkhan.nausharipov Date: Fri Feb 3 14:53:06 2023 +0600 comment fixes (#24538) commit 7f943d51dcc975f39dc666b19e107c8956fb2048 Author: darkhan.nausharipov Date: Fri Feb 3 12:48:46 2023 +0600 organized TourNotifier (#24538) commit 52227d538363a74fb96eb7410eb1d606ef34429f Author: darkhan.nausharipov Date: Fri Feb 3 12:37:55 2023 +0600 deleted unitProgressByUnitId getter (#24538) commit 4e3d3cfe134688a8e14813092d1819e97a552b01 Author: darkhan.nausharipov Date: Fri Feb 3 12:31:54 2023 +0600 alphabetic order (#24538) commit bfc759666b71f4c265285633f1b57bb3e549eabd Author: darkhan.nausharipov Date: Fri Feb 3 12:26:10 2023 +0600 getUnitSavedSnippetId (#24538) commit a836d0180e328d0bcecf614eb7178734422446ff Author: darkhan.nausharipov Date: Thu Feb 2 18:57:05 2023 +0600 comment fixes(#24538) commit 01611b02f9947d4401ed056528b92e707c619a27 Author: darkhan.nausharipov Date: Wed Feb 1 20:26:36 2023 +0600 comment fixes (#24538) comment fixes (#24538) commit fff0bfa7e4f3e68ae5ac6e7191f7600b22236dca Author: darkhan.nausharipov Date: Fri Jan 27 01:29:59 2023 +0600 save code status (#24538) commit d4401c9156a8599cb44b2f92e189906615eff5cf Author: darkhan.nausharipov Date: Thu Jan 26 14:14:18 2023 +0600 comment fixes (#24538) commit f3d1c0f66fad5072008434516ec93bb23bf1f138 Author: darkhan.nausharipov Date: Thu Jan 26 10:48:50 2023 +0600 snippet type enum switcher (#24538) commit 25dec321066e89e2ce9f1f1574b42d002c61fa80 Author: darkhan.nausharipov Date: Wed Jan 25 00:48:14 2023 +0600 comment fixes (#24538) commit f2d2f8fa304b19c6ebf7411745365e5cb59c3557 Author: darkhan.nausharipov Date: Mon Jan 23 21:32:19 2023 +0600 reverted to unitProgress (#24538) commit a5310e0eb21d00dc8e3256562e5530bc21fa496c Author: darkhan.nausharipov Date: Mon Jan 23 21:28:40 2023 +0600 missing notifyListeners (#24538) commit 18ecd23b17cc9397311c2a0a51bbef25c62e2e0b Author: darkhan.nausharipov Date: Mon Jan 23 21:26:52 2023 +0600 reset is shown immediately (#24538) commit ea8acc0d68528fd435a2134feb1ad35076114fa4 Author: darkhan.nausharipov Date: Mon Jan 23 18:58:41 2023 +0600 removed comment after discussion (#24538) commit 92b4ec47c0526523da672f4472f2776a46e40de5 Author: darkhan.nausharipov Date: Mon Jan 23 09:06:57 2023 +0600 tested with show solution (#24538) commit ebce111cc242e6f2323717c6fda0761d1e69bdc9 Author: darkhan.nausharipov Date: Sun Jan 22 22:28:47 2023 +0600 set show solution false on reset (#24538) commit ece905cfb6d8abe5fc64f3f8d023699a17047fd5 Author: darkhan.nausharipov Date: Sun Jan 22 22:08:53 2023 +0600 pre-review fixes (#24538) commit 725e8d108678c0b9da1718a478468207c1e4c446 Author: darkhan.nausharipov Date: Fri Jan 20 19:06:51 2023 +0600 post-merge commit (#24538) commit b6cb6b93e92df4571df84bdbc524a815d7ca2308 Merge: eb23673d01 428ec97e30 Author: darkhan.nausharipov Date: Fri Jan 20 19:06:03 2023 +0600 Merge branch 'master' into issue24538-save-user-code commit eb23673d0178f90b313fb18c591505f8952eb24b Author: darkhan.nausharipov Date: Fri Jan 20 18:39:35 2023 +0600 setSaveCodeListener to activeFileController.codeController (#24538) commit d3b0085253c985e52351bf541587d447db08c94d Author: darkhan.nausharipov Date: Tue Jan 17 15:28:17 2023 +0600 merge fixes (#24538) commit 8cd106d00f6369b8dec1f92ca44190ded3378d30 Merge: a8502624ca a5e6d90081 Author: darkhan.nausharipov Date: Tue Jan 17 15:27:42 2023 +0600 Merge branch 'master' into issue24538-save-user-code commit a8502624ca74909e27e5f90508c0bea22619b382 Author: darkhan.nausharipov Date: Tue Dec 27 19:06:23 2022 +0600 getUnitSnippets in unit progress (#24538) commit 8dd70984cdb3aebd676c2d92f4508b3b0d6a7ae5 Author: darkhan.nausharipov Date: Thu Dec 8 22:33:32 2022 +0600 user menu without padding commit 90b9e3d49adf6c075fbdeef881ee161b109fd1df Author: darkhan.nausharipov Date: Thu Dec 8 22:32:37 2022 +0600 save user code barely works commit 44172c57c2d806b6521fc966febabb949e3e77a7 Merge: d442e63668 59d0fd3129 Author: darkhan.nausharipov Date: Thu Dec 8 14:15:37 2022 +0600 Merge branch 'issue24394-tobf-hint' into issue24538-tobf-save-user-code commit d442e63668b15330bd8a68fb18312f5cc06e5640 Author: darkhan.nausharipov Date: Wed Dec 7 15:22:57 2022 +0600 no duplicate slash with reg exp (#24538) commit e76860497a6983cd28e29f3d4065c9331ac32660 Author: darkhan.nausharipov Date: Tue Dec 6 10:11:12 2022 +0600 updated import (#24538) commit 63745d564ace082d34be5360cfd264cfaef6e86a Merge: d15913b289 af936d0b11 Author: darkhan.nausharipov Date: Tue Dec 6 10:02:57 2022 +0600 Merge branch 'issue23692_auth' into issue24538-tobf-save-user-code commit 59d0fd3129bcab3b55a66f671898ce6c5bcc84df Author: darkhan.nausharipov Date: Fri Dec 2 20:50:12 2022 +0600 solution managed inside of tour notifier (#24394) commit 5ca484661d330a0d7bea371a767f8d37402db520 Author: darkhan.nausharipov Date: Fri Dec 2 15:57:30 2022 +0600 show solution snippets (#24394) commit 5e3ac5857e6fbe585e8f6b43cca75265b59e25c2 Author: darkhan.nausharipov Date: Fri Dec 2 14:20:43 2022 +0600 renamed to unit content widget (#24394) commit 372b97fb5cd457125137c3ceb71332acecbc9117 Author: darkhan.nausharipov Date: Fri Dec 2 12:01:39 2022 +0600 group progress indicator size adjustment (#24394) commit 48ea57d7c97a817458741d7062955add3b758c76 Author: darkhan.nausharipov Date: Fri Dec 2 11:50:08 2022 +0600 title in unit content (#24394) commit 338c67317cdc9eec5a4046af9e5599737408baf2 Author: darkhan.nausharipov Date: Fri Dec 2 11:01:57 2022 +0600 extracted widgets, hints emptiness check (#24394) commit 36d3105f52fad0aa37ddaeaac340ee31a8a4e86b Author: darkhan.nausharipov Date: Thu Dec 1 21:12:05 2022 +0600 hint in dialog (#24394) commit af936d0b115bf42f21310719dc1b18e580010421 Author: darkhan.nausharipov Date: Thu Dec 1 14:59:52 2022 +0600 added firebase_options.dart into gradle rat exclusions & added a missing license (#23692) commit 9e1bbb081c575358445750694d27e393ebd72406 Author: darkhan.nausharipov Date: Thu Dec 1 14:02:46 2022 +0600 specific imports (#23692) commit 9720c134b5733fb439ae2b4df12bff07c359a95b Author: darkhan.nausharipov Date: Thu Dec 1 13:06:57 2022 +0600 moved dismissible overlay (#23692) commit 869b40cefa9222b5a61db0125f6c54340dfc918c Author: darkhan.nausharipov Date: Thu Dec 1 13:06:40 2022 +0600 extracted overlay body (#23692) commit c8db1ef778f401a9029c113a784faeb94919d660 Author: darkhan.nausharipov Date: Thu Dec 1 13:05:12 2022 +0600 refined open overlay (#23692) commit 8b639d08b3d6101ba9b13a6f6fe32b7cc7261559 Author: darkhan.nausharipov Date: Thu Dec 1 12:50:35 2022 +0600 all caches extend cache (#23692) commit a10795205507a66b8cd90ed8caaf112663a60c8c Author: darkhan.nausharipov Date: Thu Dec 1 12:47:19 2022 +0600 renamed user progress cache to unit progress (#23692) commit e215ec4c676e88d85fad3ba08e222ac19d8953b8 Author: darkhan.nausharipov Date: Wed Nov 30 10:37:05 2022 +0600 generated files commit 96e41f7d01c50e2cfa96fbc120fca69b3d29cb39 Merge: 1e38328e56 37fb90c98d Author: darkhan.nausharipov Date: Wed Nov 30 10:30:05 2022 +0600 Merge from master commit 1e38328e564f72b4e18439c60610902423223dbd Author: darkhan.nausharipov Date: Tue Nov 29 15:40:15 2022 +0600 removed "fix exception" todo after filing an issue (#23692) commit b6c4e3e66c30fa4cbdfbbefd1a41e649c32b9ecb Author: darkhan.nausharipov Date: Tue Nov 29 13:52:29 2022 +0600 added async (#23692) commit 27b26e41a81f07faac060c3d2e45f5b7bea19d5a Author: darkhan.nausharipov Date: Tue Nov 29 13:31:24 2022 +0600 clearUpdatingUnitId (#23692) commit 4b2d855920d6d63dfff4412fc9bdfb9ddbbdd695 Author: darkhan.nausharipov Date: Tue Nov 29 13:30:12 2022 +0600 renamed user progress model to unit progress (#23692) commit ef637403aa114f43f82ac005254632f2d35e0bad Author: darkhan.nausharipov Date: Tue Nov 29 13:09:58 2022 +0600 rearranged completeUnit (#23692) commit fb1fea1af8069ae02ba261781ca923cd40796c97 Author: darkhan.nausharipov Date: Tue Nov 29 11:43:06 2022 +0600 comment fixes (4) commit 749d8b19bea072be84cace76bd1fb998a3a76531 Author: darkhan.nausharipov Date: Tue Nov 29 11:03:34 2022 +0600 pubspec.lock commit 0a76b4019647ebcbec76739b078b01fddd37789b Author: darkhan.nausharipov Date: Tue Nov 29 11:03:17 2022 +0600 pubspec.lock ignored only in PGC commit c6004b0f220be0959b1fadc1fcffb04e4004cd97 Author: darkhan.nausharipov Date: Mon Nov 28 21:17:16 2022 +0600 no final else commit d55622e30df308eb61a42ecd1f03930012ec0cb8 Author: darkhan.nausharipov Date: Mon Nov 28 21:15:15 2022 +0600 missing await commit 65dc5219943a948e7922da44ce34b54474bffaf1 Author: darkhan.nausharipov Date: Mon Nov 28 21:12:22 2022 +0600 updating & blocking complete unit button (#23692) commit 1bbc09279604dd2025ca6c93cfc85d2df9bece09 Author: darkhan.nausharipov Date: Mon Nov 28 14:36:25 2022 +0600 comment fixes (3) commit 860780836bdf8cdbbcbe5952232abc3544effc9e Author: darkhan.nausharipov Date: Mon Nov 28 12:44:52 2022 +0600 pubspec.lock in gitignore commit a575717869b239f59374caf74f81db74191c3781 Author: darkhan.nausharipov Date: Mon Nov 28 12:41:44 2022 +0600 deleted pubspec.lock commit c2f74a59ed6a364d04a9cb0d11ea0e1f0ce5ffbf Author: darkhan.nausharipov Date: Sun Nov 27 21:05:49 2022 +0600 review comments (2) commit adbdeb6eec823178d487a3a3b3bba07ceda6efa9 Author: darkhan.nausharipov Date: Thu Nov 24 15:15:57 2022 +0600 deleted file (#23692) commit 6ed38acb2beb4b960eb7a77da1282683e2805bc0 Author: darkhan.nausharipov Date: Thu Nov 24 15:14:07 2022 +0600 unused import (#23692) commit 2c90ced90376df81d0989c233995320a73c7feb1 Author: darkhan.nausharipov Date: Thu Nov 24 14:55:05 2022 +0600 login_overlay (#23692) commit 6d21e1ea3f0837616a185e4b1f0d48398799791d Author: darkhan.nausharipov Date: Thu Nov 24 14:52:08 2022 +0600 kOpenLoginOverlay (#23692) commit 64965a1e1f49f0240b4e27a387aad099caade1b2 Author: darkhan.nausharipov Date: Thu Nov 24 14:44:19 2022 +0600 canCompleteCurrentUnit (#23692) commit 7fbaf3843394530602a87805fa274ace7620ae29 Author: darkhan.nausharipov Date: Wed Nov 23 15:21:56 2022 +0600 new configs & todos commit 0b6fc8f805d3417f819ebafadc40f2571d73df99 Author: darkhan.nausharipov Date: Tue Nov 22 21:07:35 2022 +0600 candidate repository commit 3df27bc7fc71f12d48b3aa0bf5d58e57ba1327b9 Author: darkhan.nausharipov Date: Tue Nov 22 15:12:05 2022 +0600 untested refinement (1) commit 52838e500fc106414dbb47d0c05fe4042c812509 Author: darkhan.nausharipov Date: Mon Nov 21 21:54:53 2022 +0600 notifier objects naming commit 2068ce9e8da8b6caa41e1be09dfa04e26e2ca567 Author: darkhan.nausharipov Date: Mon Nov 21 21:50:25 2022 +0600 deleted show sdk selector commit a6597d434a3aed640fc230976afd3637217d8792 Author: darkhan.nausharipov Date: Mon Nov 21 21:44:55 2022 +0600 untested refinement commit 10b287b89456368b146fd9bc1edc38bf0c28fc73 Merge: 4aedd5a607 5ad067f7cc Author: Darkhan Nausharipov <31556582+nausharipov@users.noreply.github.com> Date: Mon Nov 21 19:06:30 2022 +0600 Merge pull request #324 from akvelon/tour-header-sdk-selector SDK selector in tour scaffold commit 5ad067f7ccdb976fcdb26102d983bea936a9ba83 Author: darkhan.nausharipov Date: Mon Nov 21 17:55:38 2022 +0600 non-nullable onChanged commit 4aedd5a6072e92dbfd7487652619e7a14e291375 Merge: 6f53e30d39 70c0d61d3a Author: darkhan.nausharipov Date: Mon Nov 21 16:06:38 2022 +0600 SDK selector with fixed comments commit 6f53e30d39ba793850153a2a6077fbe6bbab2b51 Author: darkhan.nausharipov Date: Mon Nov 21 16:04:31 2022 +0600 cache license commit 70c0d61d3a96e120d312f1aecc6a38e73e551697 Author: darkhan.nausharipov Date: Sat Nov 19 20:46:18 2022 +0600 comments (0) commit de273baf06cc76e4da1f94064131f0093e265f0c Author: darkhan.nausharipov Date: Fri Nov 18 20:51:31 2022 +0600 hide back button after navigating from welcome commit 3a10e8d7633bb4d6d9bd39ba5515aacae6208554 Author: darkhan.nausharipov Date: Fri Nov 18 20:48:13 2022 +0600 show sdk selector in welcome screen commit de0f7c34f2a686f22137c464d8815a5f6c2cb9c4 Author: darkhan.nausharipov Date: Fri Nov 18 20:00:17 2022 +0600 sdk selection works with auth commit 3c534d864b5a36cf4f63b64af0332753fd420b9a Merge: 12a685d1f0 b78bbd33dc Author: Darkhan Nausharipov Date: Fri Nov 18 19:41:06 2022 +0600 Merge remote-tracking branch 'origin/tour-header-sdk-selector' into auth_sdk_demo commit 12a685d1f00140981c8241a2477b5ee0707e47be Author: darkhan.nausharipov Date: Fri Nov 18 19:36:34 2022 +0600 unit file fix commit d25eaf52df834b655421319b14e43e0afc7c63f1 Merge: 5297d2548c cf56af2799 Author: Darkhan Nausharipov Date: Fri Nov 18 19:22:22 2022 +0600 Merge branch 'master' into issue23692_auth commit 5297d2548ced6027c58b75b9d917fbfeb7052369 Author: darkhan.nausharipov Date: Wed Oct 19 19:50:43 2022 +0600 auth, complete unit, user progress AuthNotifier draft (#23692) Comments (#23692) Comments (#23692)(1) sign in with google works (#23692) new configs (#23692) get user progress draft (#23692) comment fixes (#23692) sign in in IntroTextBody (#23692) reverted config (#23692) comment fixes (#23692) WIP before rebase (merge) (#23692) Squashed commit of the following: commit bff4919ff00ec3b5d7186efde41c884dfc4c8344 Merge: 79ba69483a ce8d618c77 Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Thu Nov 17 10:34:02 2022 +0100 Merge pull request #24186: Uses _all to follow alias/datastreams when estimating index size commit 79ba69483a84ea0278d0b0ddb141200739607c77 Merge: 245fea9040 b7e860a762 Author: Chamikara Jayalath Date: Wed Nov 16 20:47:40 2022 -0800 Merge pull request #24218: Update Python wheel format for RC validation commit 245fea904014cd58d4148807463dbaa40000774c Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed Nov 16 18:12:33 2022 -0800 Bump loader-utils from 1.4.1 to 1.4.2 in /sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel (#24191) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit e1de8e78deeb5d17617fda6591429eaaf8abb8a2 Author: Yi Hu Date: Wed Nov 16 20:48:06 2022 -0500 Fix PythonLint (#24219) commit b7e860a7621771c300dcec625655f87e62591323 Author: Chamikara Jayalath Date: Wed Nov 16 17:28:31 2022 -0800 updates commit c2feb09ea49dd815b69c65e531ce34128756d988 Author: Chamikara Jayalath Date: Wed Nov 16 17:06:08 2022 -0800 updates commit ce8d618c77d23e20a1ddb128bb8183048597d096 Author: egalpin Date: Wed Nov 16 16:43:57 2022 -0800 Adds test for following aliases when estimating index size commit 959719d01c627328c0ca2849d2b7e2c9b322d4d1 Author: Chamikara Jayalath Date: Wed Nov 16 15:16:06 2022 -0800 Temporary update Python RC validation job commit b952b41788acc20edbe5b75b2196f30dbf8fdeb0 Author: Yi Hu Date: Wed Nov 16 14:18:12 2022 -0500 Python TextIO Performance Test (#23951) * Python TextIO Performance Test * Add filebasedio_perf_test module for unified test framework for Python file-based IOs * Fix MetricsReader publishes metrics duplicately if more than one load test declared. This is because MetricsReader.publishers was static class variable * Fix pylint * Distribute Python performance tests random time at a day instead of all at 3PM * Add information about length conversion commit 017f2cbde124af40a43be99ec88289fcf63c1c95 Merge: fef8acdbc0 88dba4f494 Author: Chamikara Jayalath Date: Wed Nov 16 10:39:52 2022 -0800 Merge pull request #24187: Add a reference to Java RunInference example commit fef8acdbc0ecbcc85b49144adaf8830e3bc6b2de Merge: 6e9187e67e ead245539d Author: Ahmet Altay Date: Wed Nov 16 10:24:53 2022 -0800 Merge pull request #24199 from Laksh47/issue#24196 refs: issue-24196, fix broken hyperlink commit 6e9187e67e1bd8f73997f437f0ed4c29880ed73b Author: Darkhan Nausharipov <31556582+nausharipov@users.noreply.github.com> Date: Wed Nov 16 22:33:50 2022 +0600 [Tour of Beam] [Frontend] Content tree URLs (#23776) * Content tree navigation (#23593) Unit content navigation (#23593) Update URL on node click (#23593) Active unit color (#23593) removeListener in unit (#23593) First unit is opened on group title click (#23593) WIP by Alexey Inkin (#23593) selectedUnitColor (#23593) Unit borderRadius (#23593) RegExp todo (#23593) added referenced collection package to remove warning (#23593) small refinement (#23593) expand on group tap, padding, openNode (#23593) group expansion bug fix (#23593) selected & unselected progress indicators (#23593) * AnimatedBuilders instead of StatefulWidgets in unit & group (#23593) * fixed _getNodeAncestors (#23593) * get sdkId (#23593) * addressing comments (#23593) * sdkId getter & StatelessExpansionTile (#23593) * expand & collapse group (#23593) * StatelessExpansionTile (#23593) * license (#23593) * ValueChanged and ValueKey in StatelessExpansionTile (#23593) Co-authored-by: darkhan.nausharipov Co-authored-by: Alexey Inkin commit b33fac2aa533d77cfa47f88466c8cd6bd3f3e864 Author: Bruno Volpato Date: Wed Nov 16 10:51:11 2022 -0500 Use only ValueProviders in SpannerConfig (#24156) commit 5f013ab6567ec75b460b2081d7f89d332320caff Author: Robert Burke Date: Wed Nov 16 07:23:10 2022 -0800 revert upgrade to go 1.19 for action unit tests (#24189) commit 9337f4dbecc929886f8559949a082a649fd9d1bb Author: Yi Hu Date: Wed Nov 16 10:18:42 2022 -0500 Fix Python PostCommit Example CustomPTransformIT on portable (#24159) * Fix Python PostCommit Examples on portable * Fix custom_ptransform pipeline options gets modified * Specify flinkConfDir commit ead245539d01dec0f3e08699c1e1cc6777a5ef0e Author: Laksh Date: Wed Nov 16 09:32:46 2022 -0500 refs: issue-24196, fix broken hyperlink commit e83a996d4374d467d95bcfad7166905622ec615c Merge: 2fc56ec663 ffdee0b6ed Author: Jan Lukavský Date: Wed Nov 16 15:15:31 2022 +0100 Merge pull request #24192: Re-use serializable pipeline options when already available. commit ffdee0b6edb8638c78a65ec85c727ea5dde1cb2f Author: Jozef Vilcek Date: Mon Nov 14 16:48:18 2022 +0100 Re-use serializable pipeline options when already available (#24192) commit 88dba4f494829b2b3530b767fb8c5252e0d2ba44 Author: Chamikara Jayalath Date: Tue Nov 15 16:21:22 2022 -0800 Add a reference to Java RunInference example commit 2fc56ec663e335cfcf37dc57d471f79b601414f4 Merge: f763186987 83f1bc19b9 Author: Kenn Knowles Date: Tue Nov 15 16:16:47 2022 -0800 Merge pull request #24142: Fix arguments to checkState in BatchViewOverrides commit f763186987c00ba1d26efdc35406436a1fa69a9a Merge: c2bc2135e9 0d7ca04182 Author: Ning Kang Date: Tue Nov 15 15:25:20 2022 -0800 Addresses #24161 Updated README of Interactive Beam commit c2bc2135e9bce715990a5d5551e2bc2dc0311da4 Author: Doug Judd Date: Tue Nov 15 14:48:26 2022 -0800 Strip FGAC database role from changestreams metadata requests (#24177) Co-authored-by: Doug Judd commit af637974f96ad1b5110d7dea3f9a26c68e19a51b Author: Jack McCluskey <34928439+jrmccluskey@users.noreply.github.com> Date: Tue Nov 15 17:16:43 2022 -0500 Add custom inference function support to the PyTorch model handler (#24062) * Initial type def and function signature * [Draft] Add custom inference fn support to Pytorch Model Handler * Formatting * Split out default * Remove Keyed version for testing * Move device optimization * Make default available for import, add to test classes * Remove incorrect default from keyed test * Keyed impl * Fix device arg * custom inference test * formatting * Add helpers to define custom inference functions using model methods * Trailing whitespace * Unit tests * Fix incorrect getattr syntax * Type typo * Fix docstring * Fix keyed helper, add basic generate route * Modify generate() to be different than forward() * formatting * Remove extra generate() def commit a014637106970a0a0e9eb7944aa5caf79fa5fd37 Author: egalpin Date: Tue Nov 15 13:57:54 2022 -0800 Uses _all to follow alias/datastreams when estimating index size Fixes #24117 commit 0d7ca041823bc2b09f76f86fdfd1d0b9508c9c88 Author: Ning Kang Date: Tue Nov 15 13:57:27 2022 -0800 Minor update commit e8fc759d756f4a987e41d2b9da56b906a6cd7736 Author: Ning Kang Date: Tue Nov 15 13:52:18 2022 -0800 Updated README of Interactive Beam Removed deprecated cache_dir runner param in favor of the cache_root global option. commit 08d5f72e5f35d41f3e9fa9fe799caea6bed1b7a7 Author: Anand Inguva <34158215+AnandInguva@users.noreply.github.com> Date: Tue Nov 15 16:34:21 2022 -0500 [Python]Support pipe operator as Union (PEP -604) (#24106) Fixes https://github.com/apache/beam/issues/21972 commit 526e7a58b62682582c27173ab21ed8667ddab766 Author: Scott Strong Date: Tue Nov 15 16:26:45 2022 -0500 Using Teardown context instead of deprecated finalize (#24180) * Using Teardown context instead of deprecated finalize * making function public Co-authored-by: Scott Strong commit fb4d1d4dea7b26ed538a9f6aca0ed41e8c300e37 Author: Danny McCormick Date: Tue Nov 15 16:25:22 2022 -0500 Fix broken json for notebook (#24183) commit f98db2008a97f4546d036ddf0dddfee8c87eb58a Author: Robert Burke Date: Tue Nov 15 12:49:23 2022 -0800 Update automation to use Go 1.19 (#24175) Co-authored-by: lostluck <13907733+lostluck@users.noreply.github.com> commit e5f58504eef1fdeebe0402cda8a2df259169c704 Author: Brian Hulette Date: Tue Nov 15 12:25:13 2022 -0800 Add error reporting for BatchConverter match failure (#24022) * add error reporting for BatchConverters * Test pytorch * Finish up torch tests * yapf * yapf * Remove else commit 3037747f66f0d71d65b6c65745b4f8942c22f05a Author: Danny McCormick Date: Tue Nov 15 14:13:04 2022 -0500 Fix broken notebook (#24179) commit b2b1c739ce37690923891934ee317f799db937a2 Author: MakarkinSAkvelon <67736809+MakarkinSAkvelon@users.noreply.github.com> Date: Tue Nov 15 21:53:06 2022 +0500 [Playground] Move Playground in GKE and Infrastructure change (#23928) * changes to updated master branch * Change workflow * ingress changes * Certificate was added * Updates for cloud build backend * Update main.tf * Create main.tf * Create variables.tf * Update variables.tf * Update main.tf * Update variables.tf * Update main.tf * Create output.tf * Update output.tf * Update output.tf * Update main.tf * Update build.gradle.kts * Update output.tf * Update main.tf * Update main.tf * Update main.tf * Update variables.tf * Update main.tf * Update variables.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update variables.tf * Update main.tf * Update variables.tf * Update main.tf * Update variables.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update main.tf * Update output.tf * Update main.tf * Update main.tf * Update output.tf * Create variables.tf * Update main.tf * Update main.tf * Delete playground/terraform/infrastructure/cluddns directory * Update main.tf * Update output.tf * Update output.tf * Update build.gradle.kts * Update build.gradle.kts * Update build.gradle.kts * Update build.gradle.kts * Update build.gradle.kts * Update build.gradle.kts * Update README.md * Update README.md * helm folder name was changed * Update README.md * Update build.gradle.kts * Update build.gradle.kts * Update build.gradle.kts * Updates to readme * Fix DNS name * HelmChart was changed * Some workflows were changed * Remove unused file * playground-examples return * add license information * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * remove "stg" folder * Update README.md * Remove unused files * DNS Removed * var name changed * remove DNSName from var file * 1 * Clear terraform * remove unused records * gradle check * grade last change * issue fix * fix * 1 * run * test * Index creation for Gradle * Add IndexCreation in gradle * Update README.md * Update README.md * Fix names for Frontend * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Redis fix * services fix * Update variables.tf * change order in gradle * Fix Config.g.dart file issue * Update README.md * Playground workflow update Co-authored-by: Sergey Makarkin Co-authored-by: Sergey Makarkin Co-authored-by: ruslan-ikhsan Co-authored-by: Alex Kosolapov commit 85df5f2eb2f299e28b36be0cce7b9c19d62124da Author: Yi Hu Date: Tue Nov 15 11:38:13 2022 -0500 Eliminate CalciteUtil.CharType logical type (#24013) * Eliminate CalciteUtils.CharType logical type * Replace CalciteUtils.CharType to String Note that CalciteUtils still omits the precision of BINARY/VARBINARY/CHAR/VARCHAR as what it originally did. Support of the precision of these calcite types involves make use of making use of the overload method RelDataTypeFactory.createSqlType(var1, var2). * Replace every reference of CalciteUtil.CharType to generic PassThroughLogicalType check * Add TODO to Support sql types with arguments * Use VariableString in LogicalTypeTestCase commit f349f41010c5b238ff6020f7de718f938eef3c5e Author: alexeyinkin Date: Tue Nov 15 20:04:01 2022 +0400 Configure flutter_code_editor options with Hugo shortcode (#23926) (#24031) * Configure flutter_code_editor options with Hugo shortcode (#23926) * Minor fixes (#23926) * Refactor after review (#23926) commit 0f4ca6363b3ce0e5de3ad36517bb406aa6391a18 Author: Rebecca Szper <98840847+rszper@users.noreply.github.com> Date: Tue Nov 15 06:10:13 2022 -0800 Editorial review of the ML notebooks. (#24125) * Editorial review of the ML notebooks. * Editorial review of the ML notebooks. * Editorial review of the ML notebooks. * Update examples/notebooks/beam-ml/custom_remote_inference.ipynb Co-authored-by: Danny McCormick * Updating based on feedback * Update examples/notebooks/beam-ml/run_inference_sklearn.ipynb Co-authored-by: Danny McCormick * Update examples/notebooks/beam-ml/run_inference_tensorflow.ipynb Co-authored-by: Danny McCormick * Update examples/notebooks/beam-ml/run_inference_tensorflow.ipynb Co-authored-by: Danny McCormick * Update examples/notebooks/beam-ml/run_inference_tensorflow.ipynb Co-authored-by: Danny McCormick * Updating based on feedback Co-authored-by: Danny McCormick commit 5bd34ede026253326ebff1a7e4f9edb5f71b4a2c Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Nov 15 07:17:28 2022 -0500 Bump github.com/aws/aws-sdk-go-v2/feature/s3/manager in /sdks (#24131) Bumps [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) from 1.3.2 to 1.11.39. - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.3.2...feature/s3/manager/v1.11.39) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 2ee809fa0ca7689dd0279e186ebc02d9569a8429 Merge: e3b9bdb2e6 563c66d6fd Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Tue Nov 15 11:01:14 2022 +0100 Merge pull request #23065: [Website] Update copy icon styles commit e3b9bdb2e607d85a4017ba7839000e92a0ad83c4 Author: Moritz Mack Date: Tue Nov 15 10:40:50 2022 +0100 [Dockerized Jenkins] Fix build of dockerized jenkins (fixes #24053) (#24054) commit faaac2ab6e010374cb2be0e95a5dd345836a2a2c Author: Moritz Mack Date: Tue Nov 15 10:38:59 2022 +0100 [Dockerized Jenkins] Update README how to use local repo (#24055) commit 689e70b5131620540faf52e2f1e2dca7a36f269d Author: Damon Date: Mon Nov 14 17:34:29 2022 -0800 Implement embedded WebAssembly example (#24081) commit e1bf6c42950e8013f35e35fb9fee8017e01e5010 Merge: eddac84126 10337d2868 Author: Robert Bradshaw Date: Mon Nov 14 15:22:14 2022 -0800 Merge pull request #24160 Rename the test_splits flag to direct_test_splits. commit eddac841261228a2c63fa9b225c520ae0f853806 Author: Pablo Date: Mon Nov 14 15:05:05 2022 -0800 More dataset templates to clean up (#24162) commit 2adb68bd12743566cc89b596bf204d7c807eb62d Author: Pablo Date: Mon Nov 14 13:28:13 2022 -0800 Adding a quickstart to README for the TS SDK (#23509) * More of a quickstart for the TS SDK * Update sdks/typescript/README.md Co-authored-by: Danny McCormick * Update sdks/typescript/README.md Co-authored-by: Danny McCormick Co-authored-by: Danny McCormick commit 10337d28685ad5712e2ad8608977ec5c5e0e6b6b Author: Robert Bradshaw Date: Mon Nov 14 12:46:32 2022 -0800 Rename the test_splits flag to direct_test_splits. This avoids possible flag conflicts. commit 48c70cc30742b45b17a1d18ece2f0d079bee3915 Author: arne-alex <108519096+arne-alex@users.noreply.github.com> Date: Mon Nov 14 21:33:02 2022 +0100 Merge pull request #23333: Track time on Cloud Dataflow streaming data reads and export via heartbeats commit 9c83de646ab52bd0b05e3346190dd55cd68b2a8b Author: Johanna Öjeling <51084516+johannaojeling@users.noreply.github.com> Date: Mon Nov 14 21:19:44 2022 +0100 Add more tests for S3 filesystem (#24138) commit 9e9c6d797ba52b460f83131431c8e53aebbbc9ac Merge: d5d76b9745 c600444e1d Author: Ning Kang Date: Mon Nov 14 12:06:15 2022 -0800 Merge pull request #24029 from apache/dependabot/npm_and_yarn/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/loader-utils-1.4.1 Bump loader-utils from 1.4.0 to 1.4.1 in /sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel commit d5d76b974592d45de368ab641647ca5cc4ec12ec Author: Yi Hu Date: Mon Nov 14 15:03:28 2022 -0500 Support SqlTypes Date and Timestamp (MicrosInstant) in AvroUtils (#23969) * Support SqlTypes Date and Timestamp (MicrosInstant) in AvroUtils * Add TODO about java.time migration commit 330cc2010c9f4a2d4e30318bf50a4109ec1cd392 Author: Pablo Date: Mon Nov 14 12:02:10 2022 -0800 Cleanup stale BQ datasets (#24158) * Cleanup stale BQ datasets * addressing comments commit 4a044999b8ed4bcd41f816f3a23ccb5da00c4c38 Merge: e563b9dd2f 5bd75c25de Author: Heejong Lee Date: Mon Nov 14 11:16:00 2022 -0800 Merge pull request #24076 from chamikaramj/multilang_java_updates Updates Multi-lang Java quickstart commit e563b9dd2f3aa0484e6cdc08869991b5e438023e Author: Evgeny Antyshev Date: Mon Nov 14 20:56:35 2022 +0300 [Tour Of Beam] verify that unit exists when saving progress (#24118) * AIO * Update learning/tour-of-beam/backend/integration_tests/auth_test.go Co-authored-by: Danny McCormick * nit Co-authored-by: Danny McCormick commit 774923e0dd089de870bfa5c77063ae2b28f79347 Merge: 71785de528 1ad0cbc445 Author: Kenn Knowles Date: Mon Nov 14 09:52:26 2022 -0800 Merge pull request #24141: Fix checkArgument format in GcsPath commit 71785de52864313c2e3b14fe72a2a63281343617 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Nov 14 11:54:37 2022 -0500 Bump github.com/aws/aws-sdk-go-v2/config from 1.17.10 to 1.18.0 in /sdks (#24151) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.17.10 to 1.18.0. - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.17.10...config/v1.18.0) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/config dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 50d591d6cb3e799bee4e29dfc593c693a86e6276 Author: Bruno Volpato Date: Mon Nov 14 11:50:01 2022 -0500 Change DataflowBatchWorkerHarness doWork error level to INFO (#24135) commit 5a72696bfda09fdb905ba8e58b636f8494ef955f Merge: ee0a5836d6 0633fe9634 Author: Kenn Knowles Date: Mon Nov 14 08:12:12 2022 -0800 Merge pull request #24149: Remove extraneous jetbrains annotation commit ee0a5836d69b776834eb3bd9b2bd02eb5252c333 Merge: d001a69e1a 137799672e Author: Kenn Knowles Date: Mon Nov 14 08:11:00 2022 -0800 Merge pull request #24132: Fix checkArgument format string in AvroIO commit d001a69e1a58701d6ed4fcb5e3fb7a0921301dad Author: Yi Hu Date: Mon Nov 14 10:56:54 2022 -0500 Test Dataproc 2.1 with Flink load tests (#24129) * Test Dataproc 2.1 with Flink load tests * Minor fix flink_cluster script commit caabd9be52887ad70c8a4269395c893811ac6a84 Author: Israel Herraiz Date: Mon Nov 14 16:03:39 2022 +0100 Make MonotonicWatermarkEstimator work like its Java SDK equivalent (#24146) * Make MonotonicWatermarkEstimator work like its Java SDK equivalent The current implementation of MonotonicWatermarkEstimator raises an exception with late messages, which makes the watermark estimator barely usable in real world scenarios. This PR fixes #20041 by making this watermark estimator work like its Java SDK equivalent (`WatermarkEstimators.MonotonicallyIncreasing`). * Update unit tests too * Make linter happy commit 451f6b3e7f58d0a3782ad942c6a1fd9f63932024 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Nov 14 09:48:23 2022 -0500 Bump golang.org/x/net from 0.1.0 to 0.2.0 in /sdks (#24153) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.1.0 to 0.2.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/compare/v0.1.0...v0.2.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 2bb03d62e2d7dc2d8e39040fc9adebccbde74fde Merge: 4e39ef2041 623083cd0a Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Mon Nov 14 15:01:13 2022 +0100 Merge pull request #24000: [Website] Change headers size from h4,h3 to h2 commit 563c66d6fd32165da14a07747f2764c17a5d24ea Author: bulat safiullin Date: Wed Sep 7 18:28:42 2022 +0600 [Website] update pre tag copy link styles #23064 commit 4e39ef20410ee51c6040317bcd60171e64c5171f Merge: 223768f782 105ed6fedc Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Mon Nov 14 10:55:33 2022 +0100 Merge pull request #24115: [Website] update go-dependencies.md java-dependencies.md links commit 223768f782f771f0033b8d0686d86cf4c71fad75 Merge: aa0a35dabf a9da2abee6 Author: Kenn Knowles Date: Sun Nov 13 18:53:13 2022 -0800 Merge pull request #24136: Fix checkArgument format string in ExecutionStateTracker commit 0633fe9634fe61df7cbc0ecac205d81124fd504a Author: Kenneth Knowles Date: Sat Nov 12 15:15:16 2022 -0800 Remove extraneous jetbrains annotation commit 83f1bc19b95935e60ca1f4027d4b60c7e738a84a Author: Kenneth Knowles Date: Sat Nov 12 14:16:09 2022 -0800 Fix arguments to checkState in BatchViewOverrides commit 1ad0cbc44594d8405bf4b07a126265238013a02a Author: Kenneth Knowles Date: Sat Nov 12 13:41:02 2022 -0800 Fix checkArgument format in GcsPath commit aa0a35dabf9c2a0d9822faff06d939d9a77a3ab6 Author: Kenn Knowles Date: Fri Nov 11 20:26:30 2022 -0800 Fix checkArgument format string in TestStream (#24134) commit a9da2abee6455bc2cf0f18ba5f6cd7bbaeae669f Author: Kenneth Knowles Date: Fri Nov 11 16:54:27 2022 -0800 Fix checkArgument format string in ExecutionStateTracker commit 369e2ba8622d3474c14c39b941b2c618842d1e47 Author: Ryan Thompson Date: Fri Nov 11 19:46:07 2022 -0500 Add a ValidatesContainer integration test for use_sibling_sdk_workers (#24099) commit 137799672eb559a7586262e6a8a73d1ab3580e44 Author: Kenneth Knowles Date: Fri Nov 11 15:30:01 2022 -0800 Fix checkArgument format string in AvroIO commit 5d2dbf957e4e82fb3980726940df02ac67e563cd Author: Anand Inguva <34158215+AnandInguva@users.noreply.github.com> Date: Fri Nov 11 15:57:28 2022 -0500 Update staging of Python wheels (#24114) Fixes https://github.com/apache/beam/issues/24110 commit c2021bee1eba0322b43c90841397859048296b21 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri Nov 11 15:33:14 2022 -0500 Bump google.golang.org/api from 0.102.0 to 0.103.0 in /sdks (#24049) Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.102.0 to 0.103.0. - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.102.0...v0.103.0) --- updated-dependencies: - dependency-name: google.golang.org/api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 6557c91c79480b9d90573d52d257a11c2b160196 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri Nov 11 11:47:12 2022 -0800 Bump github.com/aws/aws-sdk-go-v2/service/s3 in /sdks (#24112) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.29.1 to 1.29.2. - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.29.1...service/s3/v1.29.2) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/service/s3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 96f9da1ab652156cd143d57e3aa3d94836338f2b Author: Yi Hu Date: Fri Nov 11 14:34:22 2022 -0500 More cleanup containers (#24105) * More cleanup containers * prebuilt_beam_sdk/beam_python_prebuilt_sdk no longer exists in gcr.io Add correct paths to cleanup * Bump grace time to 15 days * Run job daily as in code comment * Set grace period to 30 days commit 836766ddb83d37463e4b036f156b8d7e15e3864b Author: Ritesh Ghorse Date: Fri Nov 11 14:30:30 2022 -0500 upgrade testcontainer dependency (#24123) commit 9fcd20c3712536f2d4580beead678cdbb6fd4746 Author: Damon Date: Fri Nov 11 11:12:11 2022 -0800 Implement PubsubRowToMessage transform (#23897) * Begin PubsubRowToMessage Impl * Complete working draft * Unit tests validate user and non-user fields * Finish tests on supporting methods * Pass checks before finalizing tests * WIP * fix timestamp * finalize tests * Finalize code comments * Clean up check findings * Add InputSchemaFactory * Patch code comment typo commit 3a6fcc1ca4d07a467464ed1214a94b5c9c147295 Author: Evgeny Antyshev Date: Fri Nov 11 19:13:45 2022 +0300 disable (#24121) commit 027fb142038b45c443d87af96cac082264c43188 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri Nov 11 10:26:23 2022 -0500 Bump cloud.google.com/go/bigtable from 1.17.0 to 1.18.0 in /sdks (#24113) Bumps [cloud.google.com/go/bigtable](https://github.com/googleapis/google-cloud-go) from 1.17.0 to 1.18.0. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.17.0...pubsub/v1.18.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/bigtable dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit b2d28a64bb0837dd97e8be7f97f31f88d380f110 Author: Danny McCormick Date: Fri Nov 11 08:45:14 2022 -0500 Add TFX support in pydoc (#23960) * Add TFX support in pydoc * Wording commit 105ed6fedcb6ff33d4a43940c342a653e67cb25e Author: bulat safiullin Date: Thu Nov 10 17:47:54 2022 +0600 [Website] update go-dependencies.md java-dependencies.md programming-guide.md links #24084 commit 4b96193250a63b27721a8c5e1a3bd6ecff983093 Author: Brian Hulette Date: Thu Nov 10 16:51:06 2022 -0800 Remove TheNeuralBit from the pool of Python reviewers (#24108) commit 8f8f089a5f565f179905984cef3522a0577d9219 Author: Sanil Jain Date: Thu Nov 10 16:47:31 2022 -0800 Wire SamzaPipelineOptions to Exeption listener interface (#24109) commit b3186ba91f9bb22764d47b78eb2b7ff017080f75 Author: Ahmed Abualsaud <65791736+ahmedabu98@users.noreply.github.com> Date: Thu Nov 10 18:04:50 2022 -0500 Support using BigQueryIO Storage Read API with SchemaTransforms (#23827) * support schema transform for bq direct read method * use vendor Strings import * add BigQueryServices argument to config object * suppress nullability errors * add package-info.java file to providers subdirectory * removing accidentally created file * added documentation and moved configuration filclass into provider class * validate config params before expansion. config has a validaate me method * updated URN identifier to follow standards commit a4a94da1936d8cd2f8d1145fd2e8329fe06a2990 Author: Oleh Borysevych Date: Fri Nov 11 00:28:43 2022 +0200 fixing linter error (#24104) commit 156a6099d71a155c3379340a0b98256306e1755e Author: Danny McCormick Date: Thu Nov 10 17:26:15 2022 -0500 Add blog post on new ML resources (#24071) * Create ml-resources.md * Add ensemble notebook image * Add image link * Fix image link * Add ml-landing page image * Add image + move around * Add paragraph on upcoming changes * Remove bad whitespace commit 38742d40c895f5d38ee6ee5eb328d11b3262307e Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu Nov 10 16:12:40 2022 -0500 Bump github.com/aws/aws-sdk-go-v2/config from 1.5.0 to 1.17.10 in /sdks (#24080) Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.5.0 to 1.17.10. - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.5.0...config/v1.17.10) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/config dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 92cef32915c40d353b51529a87d8f0131b0a3538 Author: BjornPrime <32173247+BjornPrime@users.noreply.github.com> Date: Thu Nov 10 15:30:37 2022 -0500 Num failed inferences (#23830) * created test_increment_num_failed_inferences and test_num_failed_inferences_no_failures * added assertRaises to test_increment_num_failed_inferences * added num_failed_inferences to _MetricsCollector * changed error handling and update() implementation * updated metric name in tests * removed unnecessary else blocking * removed unnecessary inference_args from test_increment_failed_batches_counter() * changed final test_increment_failed_batches_counter assertion * clarified error handling and updated failed_batches_counter initialization * decreased examples array length to 1 to ensure repeatability * troubleshooting tests * trying to get test_increment_failed_batches_counter to fail as expected * corrected assertion details * simplified assertRaises and added reminder comment to assertEqual counter * lint test * lint test passed, resetting pre-commit-config.yaml * fixed lingering linting issues * shortened comment line to comply with linting * formatter worked its magic commit 2341f61d48d838ddaf2e4fb990a49987244c3513 Author: Evgeny Antyshev Date: Thu Nov 10 21:24:55 2022 +0300 [Tour Of Beam] handle CORS pre-flight requests (#24083) * cors * README * nit * nit * -headers, -cache * allow-headers * +1h cache,comment commit 36b0c8f1a76865e4dc3b1eaec1566c3ef9fd4345 Author: Evgeny Antyshev Date: Thu Nov 10 21:21:21 2022 +0300 [Playground] update snippet by persistence_key (#24056) * proto * AIO * -frontend * testify * +license * -build * index * skipKey * Update playground/backend/internal/db/datastore/datastore_db.go Co-authored-by: Danny McCormick Co-authored-by: Danny McCormick commit df553d1a4c6c6cc9b37ada2a6c84c88d8aef38b9 Author: Ahmed Abualsaud <65791736+ahmedabu98@users.noreply.github.com> Date: Thu Nov 10 13:17:36 2022 -0500 Add random string at the end of BigQuery query job name to make it resilient to retries (#24041) * add random string at the end of query job name * use deterministic temp table name commit e439f4120ef4c25aa36e5b03756dc7391bdbd211 Author: Pablo Date: Thu Nov 10 10:06:26 2022 -0800 Improving stale container cleanup script (#24040) * Improving stale container cleanup script * Avoid also latest image * Update .test-infra/tools/stale_dataflow_prebuilt_image_cleaner.sh Co-authored-by: Yi Hu * Update .test-infra/tools/stale_dataflow_prebuilt_image_cleaner.sh Co-authored-by: Yi Hu Co-authored-by: Yi Hu commit 8d585242e158babd8dd2ca5a6d5a49d353be2935 Author: Anand Inguva <34158215+AnandInguva@users.noreply.github.com> Date: Thu Nov 10 12:58:41 2022 -0500 [Python]Set pickle library at the Pipeline creation stage (#24069) Fixes https://github.com/apache/beam/issues/21615 commit 08b6a524fecc333a12ce42971733ef64ae7d02f1 Author: Janek Bevendorff Date: Thu Nov 10 18:37:09 2022 +0100 [BEAM-12792] Install pipline dependencies to temporary venv (#16658) commit 74f87b0282a23aa01ecb63288013311d207960aa Merge: 38a85b288a 383ea77bc9 Author: Robert Bradshaw Date: Thu Nov 10 09:10:37 2022 -0800 Merge pull request #23985 Support dynamic sharding in the worker. commit 38a85b288ad10171c444d4092eb969ca5de58af3 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu Nov 10 10:39:15 2022 -0500 Bump github.com/aws/aws-sdk-go-v2/service/s3 in /sdks (#24077) Bumps [github.com/aws/aws-sdk-go-v2/service/s3](https://github.com/aws/aws-sdk-go-v2) from 1.11.1 to 1.29.1. - [Release notes](https://github.com/aws/aws-sdk-go-v2/releases) - [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.11.1...service/s3/v1.29.1) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go-v2/service/s3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit c5110bae06fb9db6cace1f7657745fa97e3f58af Author: Yi Hu Date: Thu Nov 10 10:33:55 2022 -0500 Fix FhirIO javadoc format broken (#24072) commit 623083cd0a72d86c7ecba7653e9a8564861abc4d Author: bulat safiullin Date: Mon Nov 7 16:08:39 2022 +0600 [Website] change headers size from h4,h3 to h2 #24082 commit 5bd75c25de291e517cc5c5799ae4adaaaaceacb7 Author: Chamikara Jayalath Date: Wed Nov 9 18:04:28 2022 -0800 Updates Multi-lang Java quickstart commit 4522f4ce916223afb3c4edd02a7be6018d0ce5a4 Author: Trevor Gevers Date: Wed Nov 9 18:56:18 2022 -0600 Update datastore_wordcount.py (#23724) commit 96cc252348ce7229731be3c74bf5848d1b004c08 Author: tvalentyn Date: Wed Nov 9 16:08:00 2022 -0800 Remove a duplicate label (#24043) commit 62a6bd1e9317a7658810e9a0eebfe925460e8982 Author: Thiago Nunes Date: Thu Nov 10 08:45:27 2022 +1100 test: add more tests to throughput estimator (#23915) Verifies that getting the throughput when no updates have occurred for the size of the window should return 0. commit e6647c34bb367b3058c42d0201150395c534e7ce Author: Ritesh Ghorse Date: Wed Nov 9 15:12:59 2022 -0500 skip output coder field in exp request (#24066) commit 383ea77bc982416afcbbbe11a4dc1f1424670589 Author: Robert Bradshaw Date: Wed Nov 9 10:49:37 2022 -0800 Reduce flakiness of time-based split manager test. Increase wait time from a tenth to half a second. commit 539fa9159ffc116b2e79e6de2804dfdd1c1e4722 Author: Danny McCormick Date: Wed Nov 9 11:45:20 2022 -0500 Convert initialisms to all caps (#24061) * Convert initialisms to all caps * Fix test refs commit 4941b9633c6ccf9eb8aad554186aac24ca7b7492 Author: Ryan Thompson Date: Wed Nov 9 11:25:48 2022 -0500 added comments for tensorflow notebook (#23726) * added comments for tensorflow notebook * added note to string type commit 858f5048f578548a63e5e4319a7ab5363311c269 Merge: 95c121b254 1929968891 Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Wed Nov 9 16:35:19 2022 +0100 Merge pull request #24057: [Spark Dataset runner] Enable projection pushdown for Spark dataset runner commit 95c121b2549d3f8fda7668e3759b8991b55d9865 Author: Oleh Borysevych Date: Wed Nov 9 16:03:33 2022 +0200 Fix dependency mismatch in Playground Java runner (#24059) * fixing existing and potential dependency mismatch * extract grpc version commit 1929968891d629c83249c574c28db6c103ba9271 Author: Moritz Mack Date: Wed Nov 9 13:35:12 2022 +0100 [Spark Dataset runner] Enable projection pushdown for Spark dataset runner. commit 63362f5ba60a22e77e54c2df47a844f031036309 Author: Johanna Öjeling <51084516+johannaojeling@users.noreply.github.com> Date: Wed Nov 9 07:49:54 2022 +0100 [Go SDK] S3 implementation of the Beam filesystem (#23992) * Implement filesystem for S3 * Update CHANGES.md commit 73142bad2472e4516831c24a8dfb05c9acebf791 Author: Kanishk Karanawat Date: Tue Nov 8 20:46:04 2022 -0500 Handle Avro schema generation for logical data types in BigQueryAvroUtils (#23620): handle avro logical types for TableFieldSchema to Avro schema conversion Co-authored-by: Kanishk Karanawat commit 8db8fae173056c0d89a36a8a5ce0443b6b9e54fa Author: Robert Burke Date: Tue Nov 8 15:56:53 2022 -0800 [Go] Add pipeline resource hints to CHANGES.md (#24036) commit a84b7dc179fed5dfc1d48dddfb04266de3716e31 Author: Robert Bradshaw Date: Mon Nov 7 16:35:25 2022 -0800 Make mypy happy. commit b9655e7de1a682d8ec4efcafb4d610f794e1b40e Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Nov 8 12:27:38 2022 -0800 Bump cloud.google.com/go/storage from 1.27.0 to 1.28.0 in /sdks (#24028) Bumps [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) from 1.27.0 to 1.28.0. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.27.0...spanner/v1.28.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/storage dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 708e05f0dc6c0a2e62674cd0ecb8a6744ae57d3a Author: Brian Hulette Date: Tue Nov 8 12:18:23 2022 -0800 Retroactively announce Batched DoFn support in 2.42.0 Blog (#24011) * Retroactively announce Batched DoFn support in 2.42.0 * Add to blog as well commit b9ff75a18b40141a8d2340e397fd70382b3d4e8f Author: Israel Herraiz Date: Tue Nov 8 20:03:43 2022 +0100 Update my Twitter handle (#23653) commit bf621ccb88023e0bc09752978c099ac4629086e2 Author: Rebecca Szper <98840847+rszper@users.noreply.github.com> Date: Tue Nov 8 10:50:02 2022 -0800 Editorial review of the ML base API descriptions (#24026) commit f0a6ff46619ee1fd0639fa3f06e04708f69dee74 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Nov 8 13:04:03 2022 -0500 Bump cloud.google.com/go/bigtable from 1.16.0 to 1.17.0 in /sdks (#24027) Bumps [cloud.google.com/go/bigtable](https://github.com/googleapis/google-cloud-go) from 1.16.0 to 1.17.0. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.16.0...pubsub/v1.17.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/bigtable dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 7dac3f5ef40b5d24b24d9ce5bec4717284260b85 Author: Lukasz Cwik Date: Tue Nov 8 09:42:29 2022 -0800 [#21250] Trivial removal of loop over something that always has one element (#24014) Multiplexing was put into the PCollectionConsumerRegistry a long time ago and this seems to have been missed during that migration. commit a6a9b23fd5b74142c35948f10d1840b882817246 Author: Robert Burke Date: Tue Nov 8 09:19:49 2022 -0800 [Go] Pipeline Resource Hints (#23990) commit 8cf2a63cc25399109f64b84ddfcd7c74d21e61ce Author: tvalentyn Date: Tue Nov 8 09:19:16 2022 -0800 Update release notes. (#23986) commit c600444e1dfa2f4afaad056bc65fa009a60a32bb Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue Nov 8 06:22:14 2022 +0000 Bump loader-utils Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.1. - [Release notes](https://github.com/webpack/loader-utils/releases) - [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.1/CHANGELOG.md) - [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: loader-utils dependency-type: indirect ... Signed-off-by: dependabot[bot] commit 62d8bdc604dfeccae08d00225bce8c9b9c3ffb28 Merge: d4142f7eab 930c4d2d87 Author: Robert Bradshaw Date: Mon Nov 7 15:31:37 2022 -0800 Merge pull request #23789 Better surfacing of Scala support via Scio. commit 7f7713de09b3b0e400ed02ffdfcb34a6a8b6e1e4 Merge: 5f587b9339 d4142f7eab Author: Robert Bradshaw Date: Mon Nov 7 15:29:27 2022 -0800 Merge branch 'master' into javascript-liquid-sharding commit 5f587b9339b3b19ae5c5b1cf15e3ce218f75d21a Author: Robert Bradshaw Date: Mon Nov 7 15:25:33 2022 -0800 Clarifying comments. commit 60fe3cdddf9d3c27d9493b345d1f5f2a9284a76f Author: Robert Bradshaw Date: Mon Nov 7 15:06:26 2022 -0800 Update style sdks/python/apache_beam/runners/portability/fn_api_runner/fn_runner.py Co-authored-by: Danny McCormick commit d4142f7eab7d5a3d21a3d3930c448fe403880f93 Author: Robert Burke Date: Mon Nov 7 12:11:21 2022 -0800 Switch && for || to fix bug in #23889 resolution (#24017) commit 45100d708d954b25b5a884dc3c7a965f008228c6 Author: Danny McCormick Date: Mon Nov 7 14:53:24 2022 -0500 Add files then check cached diff to get untracked files commit 380d4730d3c52b5c2165bdb84aac11d0feccfe4f Author: scwhittle Date: Mon Nov 7 19:33:37 2022 +0100 Enforce splitting invariants by ensuring split state is reset in the same synchronized block as window index increments. (#23882) * Enforce splitting invariants by ensuring split state is reset in the same synchronized block as window index increments. Fixes #23881. * Add missing currentElement = null; Co-authored-by: Lukasz Cwik commit 8b3fd2e0d652045bf94b83638129bb12562ce738 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon Nov 7 10:33:26 2022 -0800 Bump google.golang.org/api from 0.101.0 to 0.102.0 in /sdks (#23957) Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.101.0 to 0.102.0. - [Release notes](https://github.com/googleapis/google-api-go-client/releases) - [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.101.0...v0.102.0) --- updated-dependencies: - dependency-name: google.golang.org/api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 9533fc3757d3041135cbe2f5078dff0855adc1f1 Author: capthiron <24925821+capthiron@users.noreply.github.com> Date: Mon Nov 7 19:32:18 2022 +0100 feat: implement bigtable io connector with write capabilities (#23411) commit c4218e572aa8a8f46b433b60073a59fdd7fdf148 Merge: 23676a9ec1 a5ee669a43 Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Mon Nov 7 18:24:45 2022 +0100 Merge pull request #23934: [Website] change case studies page mobile layout commit 23676a9ec17069b309e8803d1fbfeb8009035828 Author: Oleh Borysevych Date: Mon Nov 7 17:24:59 2022 +0200 [Tour of Beam] Learning content for "Introduction" module (#23085) * learning content for introduction module * removing white spaces from md files * delete whitespaces * delete whitespaces in python * delete whitespace #2 * divide pipeline concepts * add pipeline example concepts * adding category tag to python examples * adding category to java examples * adding category to go examples * fixed go example * fixed go example compilation * fixing python duplicate example names * add runner concepts * fixing java examples * add licence for runner unit * some minor fixes for unit names * fixed unit name * resolving CR comments * adding complexity to examples * adding tags * fixed go example compilation * fixed python example with duplicate transform * change indent python * fixing missing pipeline options * change arrow symbol * delete example prefix * minor formatting and readability fixes * add example description * minor fix * minor code review comment Co-authored-by: Abzal Tuganbay commit 98d2ffd69ab9d5c49196a78f7c25daacb57b6478 Author: Brian Hulette Date: Mon Nov 7 07:03:12 2022 -0800 Make `documentation/io/connectors/` canonical (#23877) * Drop documentation/io/built-in/ * Update links in Custom I/O pattern commit c0b41fa045418beb782c0a59e6f5c511da898c53 Author: Danny McCormick Date: Mon Nov 7 09:29:08 2022 -0500 Use git diff instead of git diff-index to avoid file timestamp changes being picked up commit 0476d6498217b7b0e833643c47fef2c4bdaec529 Merge: 1d5fc14031 6ae37b6f82 Author: Alexey Romanenko <33895511+aromanenko-dev@users.noreply.github.com> Date: Mon Nov 7 15:28:59 2022 +0100 Merge pull request #23962: [CdapIO] Add sparkreceiver:2 module. commit 1d5fc14031d583e92018ebfbeaff9b4e3b978fdb Author: Danny McCormick Date: Mon Nov 7 09:14:24 2022 -0500 Remove quiet flag on debug commit c08273b9355566181d2d5c0792130f8d5cc1428c Author: Danny McCormick Date: Mon Nov 7 09:12:26 2022 -0500 Correctly print diff and swallow empty commits for the moment commit 66fb431deb77db5f7f0fac31e6bf3b2c094c8ac5 Author: Danny McCormick Date: Mon Nov 7 09:08:53 2022 -0500 Print diff and scope to state path commit e0e10b9e5432643b884c381d145e5924cc4ef193 Author: Danny McCormick Date: Sun Nov 6 12:12:22 2022 -0500 PR Bot - Dont throw error on return code 1 commit bbcb790461c47d22399c681cd42c434b206eb550 Author: Danny McCormick Date: Sun Nov 6 11:59:32 2022 -0500 Fix pr bot - exec doesn't allow command chaining commit 88f9a66a9f4cc2fe3259d5ebd83ebb472a29dd5e Author: Danny McCormick Date: Sun Nov 6 11:46:34 2022 -0500 Fix diff to stop repeated bot runs commit ddb4f2d53538fea68383fe43221d4074d05d11b9 Author: bullet03 Date: Fri Nov 4 16:11:10 2022 -0700 Website add and update logos (#23899) * [Website] add and update logos * Delete talend.svg:Zone.Identifier commit 6d42219ff547720996489aa29de0d64246db2541 Author: Robert Bradshaw Date: Fri Nov 4 14:30:18 2022 -0700 Enable more portable-runner requiring tests. (#23970) * Enable more portable-runner requiring tests. * Run all basic tests on portable runner as well. * Mark ULR tests. commit 1a643d16112a5f3f1418f1be393de51af65d752b Author: David Cavazos Date: Fri Nov 4 13:45:12 2022 -0700 Beam starter projects blog post (#23964) Co-authored-by: Ahmet Altay commit d10b4a28fff667289c146152535275035f2dedf7 Author: Ryan Thompson Date: Fri Nov 4 16:06:49 2022 -0400 removed trailing whitespace (#23987) commit 3bd697561aab4a5d2aa49d29143695d6d57a834a Author: Robert Bradshaw Date: Fri Nov 4 11:43:47 2022 -0700 Add dynamic splitting support to the worker. commit ed520243f472c7224a1f8c74a0c2e8f81965cbfc Author: Robert Bradshaw Date: Fri Nov 4 11:07:40 2022 -0700 Add the a Reshuffle operation and use it in Create. This allows created sources to be staticly and dynamically split. commit 9283512544b8de169be9cd7795b42284fdf45b87 Author: Robert Bradshaw Date: Fri Nov 4 10:28:51 2022 -0700 Add the ability to schedule splits on the ULR via a pipeline option. This can be used to test arbitrary SDKs for behavioral correctness for dynamic splitting. These splits are wall-time based, which isn't ideal, but easier than setting up and managing a cross-process synchronization channel. commit ed7b560d7ce7dda0b55a067b9d9a1a9d692a7d7a Author: Robert Bradshaw Date: Fri Nov 4 09:46:19 2022 -0700 Compute element counts for all PCollections. commit 1cfdb127983a55c77b3259c4fdd248497b28e250 Author: Jack McCluskey <34928439+jrmccluskey@users.noreply.github.com> Date: Fri Nov 4 15:43:16 2022 -0400 Add custom inference fn suport to the sklearn model handlers (#23642) * Add custom inference fn suport to the sklearn model handlers * Clean up import order * Update typing, add numpy unit test * Add Pandas unit test * Formatting, linting * yapf run * Remove trailing whitespace * import order * Change inference_fn to keyword-only arg commit 8617b86fd792ac555233dd79c8ede34c2ce67ecf Merge: aa178f8252 2496a0d1e0 Author: Robert Bradshaw Date: Fri Nov 4 11:42:21 2022 -0700 Merge pull request #23978 Add basic counter support to the typescript SDK. commit 2496a0d1e0fda74e8fc0f24eee011362426369a2 Merge: 64abcbe4a3 aa178f8252 Author: Robert Bradshaw Date: Fri Nov 4 11:15:47 2022 -0700 Merge branch 'master' into javascript-metrics commit aa178f825223cbb0a6208fad0e02f98292eeded1 Merge: 97628802fe 1807c307aa Author: Robert Bradshaw Date: Fri Nov 4 09:34:11 2022 -0700 Merge pull request #23976 Correctly capture log levels and attach stage information. commit 64abcbe4a3a15160aba3f3163ff8cbf5186bbfdb Author: Robert Bradshaw Date: Fri Nov 4 09:27:22 2022 -0700 Only report counters that were actually used. commit 1807c307aa1e493acb2d8ba542baffefcb96e7e2 Author: Robert Bradshaw Date: Fri Nov 4 08:52:21 2022 -0700 Remove obsolete TODO. commit 97628802fe4cf6640a3b6854e27b410dd5731379 Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri Nov 4 11:47:07 2022 -0400 Bump cloud.google.com/go/datastore from 1.8.0 to 1.9.0 in /sdks (#23916) Bumps [cloud.google.com/go/datastore](https://github.com/googleapis/google-cloud-go) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/asset/v1.8.0...asset/v1.9.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/datastore dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> commit 058c56af735e10184d1501cc08cd16af4d21e64a Author: Ayush Sharma <114604338+ayushthe1@users.noreply.github.com> Date: Fri Nov 4 20:58:11 2022 +0530 [Task]: PR Bot will push commits only if they are non-empty (#23937) * fix pr-bot * fix the git pr bot commit 7dba78d611089a1826c5655ed7ffcdf3f6007eae Author: Danny McCormick Date: Fri Nov 4 09:35:16 2022 -0400 Immediately truncate full restriction on drain of periodic impulse (#23765) * Immediately truncate full restriction on drain of periodic impulse * Whitespace format commit 16852518861514a56ad1b57113e3815cfcc8533a Author: Anand Inguva <34158215+AnandInguva@users.noreply.github.com> Date: Fri Nov 4 08:39:34 2022 -0400 TFX image classification example (#23456) * TFX image classification example * TFX image classification with serving model * Add TF Model Wrapper * Clean up code * Refactoring * Add a test for tfx_bsl RunInference * fixup lint * Refactoring * Fixup lint * Add brief summary for the example * Apply suggestions from code review Co-authored-by: Andy Ye * Refactoring code and add comments * Update help description * reorder imports * Reorder imports again * Add docstring * Refactoring * Add pillow to tfx pipeline requirements * Move inferencePostCommitIT to Python 3.9 suite * Uncomment other postcommit suites Co-authored-by: Andy Ye commit 30b26171b4038c1c976adbc3be386e118b35153b Author: Danny McCormick Date: Fri Nov 4 08:22:17 2022 -0400 Update watermark during periodic sequence/impulse (#23507) * Update watermark during periodic sequence/impulse * Remove extraneous import * Formatting * Linting * Only run on dataflow for guaranteed watermark support * More permissive test to avoid timing issues * Test pipeline options * Fix test * Formatting * Formatting * Apply feedback - cleanup/naming/flink * Format * Unused import commit 1563b9721b4bee5a22d384b282762726247e0703 Author: Brian Hulette Date: Fri Nov 4 05:09:39 2022 -0700 Improve Iterator error message (#23972) commit e3987b5435d39c5fb058d4085eb5e210f8756224 Author: Robert Bradshaw Date: Thu Nov 3 17:39:49 2022 -0700 old prettier change commit 89c8dd5ca23591be6c2778045df32c7d08d9f99e Author: Robert Bradshaw Date: Thu Nov 3 17:12:26 2022 -0700 Add distribution metric type. commit e4e606a8f2652c2fa761a95462f230385b6bcb47 Author: Robert Bradshaw Date: Thu Nov 3 17:09:03 2022 -0700 Support metrics over the portability API. commit e04f3d6fdb39528264cb2a14e60e565991121f1c Author: Robert Bradshaw Date: Thu Nov 3 16:52:51 2022 -0700 Add basic counter setting and getting to the typescript SDK. commit 1daa9c373ac7fbdb696120eeaa2ca9e85a679a1f Author: Robert Bradshaw Date: Thu Nov 3 16:01:59 2022 -0700 Cleanup worker logging. Attempt to correctly capture and propagate log levels and attaches stage information to them. Also remove some excessively verbose logs. commit d3a173cf16355bfe23a9d918afa12cd61d290b59 Author: Robert Bradshaw Date: Thu Nov 3 15:11:40 2022 -0700 Move logging to its own module. commit 6ae37b6f82ae3cd77cc82aff4566d8218a8acc57 Author: vitaly.terentyev Date: Thu Nov 3 19:44:54 2022 +0400 Fix sparkreceiver dependencies commit 8223375d2f9606a29d6498a73c1914a61f3277c4 Author: vitaly.terentyev Date: Thu Nov 3 19:34:04 2022 +0400 Add sparkreceiver:2 module. commit a5ee669a439dc3d13dfc4926c1c5ae2351bb9135 Author: bulat safiullin Date: Wed Nov 2 13:53:08 2022 +0600 [Website] change case-study-card width on mobile commit 930c4d2d87d462b2457369fd06066203a6628a46 Author: Robert Bradshaw Date: Fri Oct 21 12:22:13 2022 -0700 Better surfacing of Scala support via Scio. draft working code test commit Revert "Squashed commit of the following:" This reverts commit 8fc833a5e7abf4cbfb63e56d450631bbfc1985ff. auth files commit b78bbd33dc518c57d92c3261e020ab12b7ea9d33 Author: darkhan.nausharipov Date: Wed Nov 16 14:46:07 2022 +0600 remove listener commit 9d1f49bb44e6dd4e24254b750fef751e8d554f23 Author: darkhan.nausharipov Date: Tue Nov 15 15:29:06 2022 +0600 StorageKeys commit 83c9c0e80288b0e2e34044285b3e626462ea9e9d Author: darkhan.nausharipov Date: Tue Nov 15 10:44:51 2022 +0600 moved AppNotifier into _initializeState commit 497ff7cf40af947a29e1ebf81163ef315ca4ecfb Author: darkhan.nausharipov Date: Mon Nov 14 23:29:45 2022 +0600 AppNotifier commit 5b07e91391383a7f6c6d40379a1787a8f3003da7 Author: darkhan.nausharipov Date: Mon Nov 14 18:49:34 2022 +0600 optional SDK selector in tour scaffold commit e4dee7bad46970ceda1fbb448fe527b8a566237f Author: darkhan.nausharipov Date: Fri Nov 11 12:15:20 2022 +0600 ValueChanged and ValueKey in StatelessExpansionTile (#23593) commit 8dc77197d63552a6664643842017f38a9ae57e66 Author: darkhan.nausharipov Date: Thu Nov 10 14:07:00 2022 +0600 license (#23593) commit 85e12348b44d1422414cdc74bb46623602ebda1c Author: darkhan.nausharipov Date: Wed Nov 9 19:55:01 2022 +0600 StatelessExpansionTile (#23593) commit 28cb6b8045409c6fd0915eedb89562c576cbd427 Author: darkhan.nausharipov Date: Wed Nov 9 16:09:02 2022 +0600 expand & collapse group (#23593) commit 57800ee5aa4b775d0fb4bcd2152a855edf724608 Author: darkhan.nausharipov Date: Wed Nov 9 10:00:02 2022 +0600 sdkId getter & StatelessExpansionTile (#23593) commit 2ab4b3bbda36879c8d19c0f1f7ddeaa6ec2234d7 Author: darkhan.nausharipov Date: Wed Nov 9 02:49:50 2022 +0600 addressing comments (#23593) commit 8e8d8c9001b8d238cd45761ced9e9f8afa38f7d9 Author: darkhan.nausharipov Date: Sat Nov 5 14:21:03 2022 +0300 get sdkId (#23593) commit 8807c00d673152762237348aeedd54e9d2aac934 Author: darkhan.nausharipov Date: Sat Nov 5 14:20:40 2022 +0300 fixed _getNodeAncestors (#23593) commit 5978d374b850c3c1b343cd92bf00d0f90af55958 Author: darkhan.nausharipov Date: Fri Nov 4 17:25:35 2022 +0300 AnimatedBuilders instead of StatefulWidgets in unit & group (#23593) commit 7c2303343812c3d0886dcb4bf2b10c3b28f9ea0a Author: darkhan.nausharipov Date: Fri Oct 21 17:32:30 2022 +0600 Content tree navigation (#23593) Unit content navigation (#23593) Update URL on node click (#23593) Active unit color (#23593) removeListener in unit (#23593) First unit is opened on group title click (#23593) WIP by Alexey Inkin (#23593) selectedUnitColor (#23593) Unit borderRadius (#23593) RegExp todo (#23593) added referenced collection package to remove warning (#23593) small refinement (#23593) expand on group tap, padding, openNode (#23593) group expansion bug fix (#23593) selected & unselected progress indicators (#23593) --- .../frontend/assets/translations/en.yaml | 3 + .../frontend/lib/cache/unit_content.dart | 9 +- .../frontend/lib/cache/unit_progress.dart | 136 ++++-- .../tour-of-beam/frontend/lib/config.dart | 10 +- .../lib/constants/hive_box_names.dart | 28 ++ .../frontend/lib/constants/sizes.dart | 1 + .../frontend/lib/enums/save_code_status.dart | 23 + .../frontend/lib/enums/snippet_type.dart | 23 + .../frontend/lib/firebase_options.dart | 12 +- .../tour-of-beam/frontend/lib/locator.dart | 12 +- .../frontend/lib/models/unit_content.g.dart | 6 +- .../frontend/lib/models/unit_progress.dart | 6 +- .../frontend/lib/models/unit_progress.g.dart | 8 + .../frontend/lib/pages/tour/path.dart | 9 +- .../frontend/lib/pages/tour/state.dart | 263 +++++++--- .../pages/tour/widgets/binary_progress.dart | 5 +- .../tour/widgets/complete_unit_button.dart | 15 +- .../lib/pages/tour/widgets/hints.dart | 30 +- .../tour/widgets/markdown/code_builder.dart | 27 +- .../pages/tour/widgets/solution_button.dart | 67 --- .../lib/pages/tour/widgets/unit_content.dart | 178 ++++--- .../frontend/lib/pages/welcome/screen.dart | 5 +- .../lib/repositories/client/client.dart | 8 + .../client/cloud_functions_client.dart | 26 + .../user_progress/abstract.dart} | 42 +- .../lib/repositories/user_progress/cloud.dart | 75 +++ .../lib/repositories/user_progress/hive.dart | 123 +++++ learning/tour-of-beam/frontend/pubspec.lock | 452 +++++++++--------- learning/tour-of-beam/frontend/pubspec.yaml | 5 +- .../frontend/lib/controllers/factories.dart | 2 +- .../handlers/set_content_message_handler.dart | 2 +- .../lib/playground_components.dart | 1 + .../example_loaders/examples_loader.dart | 7 +- .../example_loaders/hive_example_loader.dart | 49 ++ .../standard_example_loader.dart | 24 +- .../lib/src/models/dataset.dart | 10 + .../lib/src/models/dataset.g.dart | 23 + .../lib/src/models/example.dart | 14 + .../lib/src/models/example.g.dart | 72 +++ .../lib/src/models/example_base.dart | 9 + .../lib/src/models/example_base.g.dart | 63 +++ .../hive_example_loading_descriptor.dart | 78 +++ .../lib/src/models/example_view_options.dart | 14 + .../src/models/example_view_options.g.dart | 31 ++ .../lib/src/models/sdk.dart | 33 +- .../lib/src/models/sdk.g.dart | 5 + .../lib/src/theme/theme.dart | 1 + .../playground_components/pubspec.yaml | 4 +- .../example_loaders/examples_loader_test.dart | 6 +- .../hive_example_loader_test.dart | 62 +++ .../playground_controller_test.dart | 2 +- .../playground_controller_test.mocks.dart | 10 + .../hive_example_loading_descriptor_test.dart | 52 ++ .../example_selector_state_test.mocks.dart | 10 + 54 files changed, 1616 insertions(+), 575 deletions(-) create mode 100644 learning/tour-of-beam/frontend/lib/constants/hive_box_names.dart create mode 100644 learning/tour-of-beam/frontend/lib/enums/save_code_status.dart create mode 100644 learning/tour-of-beam/frontend/lib/enums/snippet_type.dart delete mode 100644 learning/tour-of-beam/frontend/lib/pages/tour/widgets/solution_button.dart rename learning/tour-of-beam/frontend/lib/{pages/tour/controllers/unit.dart => repositories/user_progress/abstract.dart} (52%) create mode 100644 learning/tour-of-beam/frontend/lib/repositories/user_progress/cloud.dart create mode 100644 learning/tour-of-beam/frontend/lib/repositories/user_progress/hive.dart create mode 100644 playground/frontend/playground_components/lib/src/controllers/example_loaders/hive_example_loader.dart create mode 100644 playground/frontend/playground_components/lib/src/models/dataset.g.dart create mode 100644 playground/frontend/playground_components/lib/src/models/example.g.dart create mode 100644 playground/frontend/playground_components/lib/src/models/example_base.g.dart create mode 100644 playground/frontend/playground_components/lib/src/models/example_loading_descriptors/hive_example_loading_descriptor.dart create mode 100644 playground/frontend/playground_components/lib/src/models/example_view_options.g.dart create mode 100644 playground/frontend/playground_components/test/src/controllers/example_loaders/hive_example_loader_test.dart create mode 100644 playground/frontend/playground_components/test/src/models/example_loading_descriptors/hive_example_loading_descriptor_test.dart diff --git a/learning/tour-of-beam/frontend/assets/translations/en.yaml b/learning/tour-of-beam/frontend/assets/translations/en.yaml index 50824aeebaecb..4644b6554f91a 100644 --- a/learning/tour-of-beam/frontend/assets/translations/en.yaml +++ b/learning/tour-of-beam/frontend/assets/translations/en.yaml @@ -44,6 +44,9 @@ pages: showSolution: Show the solution solution: Solution solveYourself: Before revealing the solution, try solving the challenge on your own. Remember, the more you practice, the better you will become. Give it a shot and see how far you can get. + example: Example + myCode: My code + saving: Saving... summaryTitle: Table of Contents dialogs: diff --git a/learning/tour-of-beam/frontend/lib/cache/unit_content.dart b/learning/tour-of-beam/frontend/lib/cache/unit_content.dart index d8499a641e272..8470ca3115d8d 100644 --- a/learning/tour-of-beam/frontend/lib/cache/unit_content.dart +++ b/learning/tour-of-beam/frontend/lib/cache/unit_content.dart @@ -29,13 +29,16 @@ class UnitContentCache extends Cache { final _unitContents = >{}; final _futures = >>{}; - UnitContentModel? getUnitContent(String sdkId, String unitId) { + Future getUnitContent( + String sdkId, + String unitId, + ) async { final future = _futures[sdkId]?[unitId]; if (future == null) { - unawaited(_loadUnitContent(sdkId, unitId)); + await _loadUnitContent(sdkId, unitId); } - return _unitContents[sdkId]?[unitId]; + return _unitContents[sdkId]![unitId]!; } Future _loadUnitContent(String sdkId, String unitId) async { diff --git a/learning/tour-of-beam/frontend/lib/cache/unit_progress.dart b/learning/tour-of-beam/frontend/lib/cache/unit_progress.dart index 5649e7464674d..51673d443be10 100644 --- a/learning/tour-of-beam/frontend/lib/cache/unit_progress.dart +++ b/learning/tour-of-beam/frontend/lib/cache/unit_progress.dart @@ -18,23 +18,92 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:get_it/get_it.dart'; +import 'package:playground_components/playground_components.dart'; import '../auth/notifier.dart'; +import '../enums/snippet_type.dart'; import '../enums/unit_completion.dart'; +import '../models/unit_progress.dart'; +import '../repositories/client/client.dart'; import '../repositories/models/get_user_progress_response.dart'; +import '../repositories/user_progress/abstract.dart'; +import '../repositories/user_progress/cloud.dart'; +import '../repositories/user_progress/hive.dart'; import '../state.dart'; -import 'cache.dart'; -class UnitProgressCache extends Cache { - UnitProgressCache({required super.client}); +class UnitProgressCache extends ChangeNotifier { + final _cloudUserProgressRepository = CloudUserProgressRepository( + client: GetIt.instance.get(), + ); + final _localStorageUserProgressRepository = HiveUserProgressRepository(); + + AbstractUserProgressRepository _getUserProgressRepository() { + if (isAuthenticated) { + return _cloudUserProgressRepository; + } + return _localStorageUserProgressRepository; + } + + Future? _future; + + var _unitProgress = []; + final _unitProgressByUnitId = {}; final _completedUnitIds = {}; final _updatingUnitIds = {}; - Future? _future; + + bool get isAuthenticated => + GetIt.instance.get().isAuthenticated; + + Future loadUnitProgress(Sdk sdk) async { + _future = _getUserProgressRepository().getUserProgress(sdk); + final result = await _future; + + _unitProgressByUnitId.clear(); + if (result != null) { + _unitProgress = result.units; + for (final unitProgress in _unitProgress) { + _unitProgressByUnitId[unitProgress.id] = unitProgress; + } + } else { + _unitProgress = []; + } + notifyListeners(); + } + + List _getUnitProgress() { + if (_future == null) { + unawaited(loadUnitProgress(GetIt.instance.get().sdk!)); + } + return _unitProgress; + } + + // Completion + + Future completeUnit(String sdkId, String unitId) async { + try { + addUpdatingUnitId(unitId); + await _getUserProgressRepository().completeUnit(sdkId, unitId); + } finally { + await loadUnitProgress(GetIt.instance.get().sdk!); + clearUpdatingUnitId(unitId); + } + } Set getUpdatingUnitIds() => _updatingUnitIds; + Set getCompletedUnits() { + _completedUnitIds.clear(); + for (final unitProgress in _getUnitProgress()) { + if (unitProgress.isCompleted) { + _completedUnitIds.add(unitProgress.id); + } + } + return _completedUnitIds; + } + void addUpdatingUnitId(String unitId) { _updatingUnitIds.add(unitId); notifyListeners(); @@ -52,6 +121,14 @@ class UnitProgressCache extends Cache { return _getUnitCompletion(unitId) == UnitCompletion.uncompleted; } + bool isUnitCompleted(String? unitId) { + return getCompletedUnits().contains(unitId); + } + + String? getUnitSavedSnippetId(String? unitId) { + return _unitProgressByUnitId[unitId]?.userSnippetId; + } + UnitCompletion _getUnitCompletion(String unitId) { final authNotifier = GetIt.instance.get(); if (!authNotifier.isAuthenticated) { @@ -66,38 +143,33 @@ class UnitProgressCache extends Cache { return UnitCompletion.uncompleted; } - bool isUnitCompleted(String? unitId) { - return getCompletedUnits().contains(unitId); - } + // Snippet - Future updateCompletedUnits() async { - final sdkId = GetIt.instance.get().sdkId; - if (sdkId != null) { - await _loadCompletedUnits(sdkId); - } + bool hasSavedSnippet(String? unitId) { + return _unitProgressByUnitId[unitId]?.userSnippetId != null; } - Set getCompletedUnits() { - if (_future == null) { - unawaited(updateCompletedUnits()); - } - - return _completedUnitIds; + Future saveSnippet({ + required Sdk sdk, + required List snippetFiles, + required SnippetType snippetType, + required String unitId, + }) async { + await _getUserProgressRepository().saveUnitSnippet( + sdk: sdk, + snippetFiles: snippetFiles, + snippetType: snippetType, + unitId: unitId, + ); } - Future _loadCompletedUnits(String sdkId) async { - _future = client.getUserProgress(sdkId); - final result = await _future; - - _completedUnitIds.clear(); - if (result != null) { - for (final unitProgress in result.units) { - if (unitProgress.isCompleted) { - _completedUnitIds.add(unitProgress.id); - } - } - } - - notifyListeners(); + Future getSavedDescriptor({ + required Sdk sdk, + required String unitId, + }) async { + return _getUserProgressRepository().getSavedDescriptor( + sdk: sdk, + unitId: unitId, + ); } } diff --git a/learning/tour-of-beam/frontend/lib/config.dart b/learning/tour-of-beam/frontend/lib/config.dart index b7ed542e1b05d..8f51d565fb716 100644 --- a/learning/tour-of-beam/frontend/lib/config.dart +++ b/learning/tour-of-beam/frontend/lib/config.dart @@ -18,8 +18,8 @@ // TODO(alexeyinkin): Generate this file on deployment. -const _cloudFunctionsProjectRegion = 'us-central1'; -const _cloudFunctionsProjectId = 'tour-of-beam-2'; +const _cloudFunctionsProjectRegion = 'us-east1'; +const _cloudFunctionsProjectId = 'river-key-378010'; const cloudFunctionsBaseUrl = 'https://' '$_cloudFunctionsProjectRegion-$_cloudFunctionsProjectId' '.cloudfunctions.net'; @@ -27,10 +27,8 @@ const cloudFunctionsBaseUrl = 'https://' // Copied from Playground's config.g.dart const String kAnalyticsUA = 'UA-73650088-2'; -const String kApiClientURL = - 'https://backend-router-beta-dot-apache-beam-testing.appspot.com'; -const String kApiJavaClientURL = - 'https://backend-java-beta-dot-apache-beam-testing.appspot.com'; +const String kApiClientURL = 'https://router.play-dev.beam.apache.org'; +const String kApiJavaClientURL = 'https://java.play-dev.beam.apache.org'; const String kApiGoClientURL = 'https://backend-go-beta-dot-apache-beam-testing.appspot.com'; const String kApiPythonClientURL = diff --git a/learning/tour-of-beam/frontend/lib/constants/hive_box_names.dart b/learning/tour-of-beam/frontend/lib/constants/hive_box_names.dart new file mode 100644 index 0000000000000..c3900ccc5823c --- /dev/null +++ b/learning/tour-of-beam/frontend/lib/constants/hive_box_names.dart @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:playground_components/playground_components.dart'; + +class HiveBoxNames { + static const unitProgress = 'unit_progress'; + static const snippets = 'snippets'; + + static String getSdkBoxName(Sdk sdk, String boxName) { + return '${sdk.id}_$boxName'; + } +} diff --git a/learning/tour-of-beam/frontend/lib/constants/sizes.dart b/learning/tour-of-beam/frontend/lib/constants/sizes.dart index 53ad1c7c2d03c..9bd2c9477622e 100644 --- a/learning/tour-of-beam/frontend/lib/constants/sizes.dart +++ b/learning/tour-of-beam/frontend/lib/constants/sizes.dart @@ -19,6 +19,7 @@ class TobSizes { static const double footerHeight = 35; static const double authOverlayWidth = 260; + static const double hintPopupWidth = 510; } class ScreenSizes { diff --git a/learning/tour-of-beam/frontend/lib/enums/save_code_status.dart b/learning/tour-of-beam/frontend/lib/enums/save_code_status.dart new file mode 100644 index 0000000000000..cd5d302a198a0 --- /dev/null +++ b/learning/tour-of-beam/frontend/lib/enums/save_code_status.dart @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +enum SaveCodeStatus { + error, + saved, + saving, +} diff --git a/learning/tour-of-beam/frontend/lib/enums/snippet_type.dart b/learning/tour-of-beam/frontend/lib/enums/snippet_type.dart new file mode 100644 index 0000000000000..202d1c6fb9da5 --- /dev/null +++ b/learning/tour-of-beam/frontend/lib/enums/snippet_type.dart @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +enum SnippetType { + original, + saved, + solution, +} diff --git a/learning/tour-of-beam/frontend/lib/firebase_options.dart b/learning/tour-of-beam/frontend/lib/firebase_options.dart index e2a871d637b36..daf07103bf3d3 100644 --- a/learning/tour-of-beam/frontend/lib/firebase_options.dart +++ b/learning/tour-of-beam/frontend/lib/firebase_options.dart @@ -53,11 +53,11 @@ class DefaultFirebaseOptions { } static const FirebaseOptions web = FirebaseOptions( - apiKey: 'AIzaSyBtAreurqJ5D4IK6cNisZh5dnDRKljbJAw', - authDomain: 'astest-369409.firebaseapp.com', - projectId: 'astest-369409', - storageBucket: 'astest-369409.appspot.com', - messagingSenderId: '534850967604', - appId: '1:534850967604:web:55c6af8da7940df1ddd261', + apiKey: 'AIzaSyD-yN7OO9xjPQ5M-SJug96M2EfHwvjzd1A"', + authDomain: 'river-key-378010.firebaseapp.com"', + projectId: 'us-east1-river-key-378010', + storageBucket: 'river-key-378010.appspot.com', + messagingSenderId: '11155893632', + appId: '1:11155893632:web:0154abc4765db232086565', ); } diff --git a/learning/tour-of-beam/frontend/lib/locator.dart b/learning/tour-of-beam/frontend/lib/locator.dart index 4c11cab0a7f82..2b0576932bd6e 100644 --- a/learning/tour-of-beam/frontend/lib/locator.dart +++ b/learning/tour-of-beam/frontend/lib/locator.dart @@ -45,11 +45,13 @@ void _initializeAuth() { } void _initializeCaches() { - GetIt.instance.registerSingleton(_client); - GetIt.instance.registerSingleton(ContentTreeCache(client: _client)); - GetIt.instance.registerSingleton(SdkCache(client: _client)); - GetIt.instance.registerSingleton(UnitContentCache(client: _client)); - GetIt.instance.registerSingleton(UnitProgressCache(client: _client)); + final client = CloudFunctionsTobClient(); + + GetIt.instance.registerSingleton(client); + GetIt.instance.registerSingleton(ContentTreeCache(client: client)); + GetIt.instance.registerSingleton(SdkCache(client: client)); + GetIt.instance.registerSingleton(UnitContentCache(client: client)); + GetIt.instance.registerSingleton(UnitProgressCache()); } void _initializeState() { diff --git a/learning/tour-of-beam/frontend/lib/models/unit_content.g.dart b/learning/tour-of-beam/frontend/lib/models/unit_content.g.dart index 8c3db0eb223bf..3dea5500e88e9 100644 --- a/learning/tour-of-beam/frontend/lib/models/unit_content.g.dart +++ b/learning/tour-of-beam/frontend/lib/models/unit_content.g.dart @@ -9,11 +9,11 @@ part of 'unit_content.dart'; UnitContentModel _$UnitContentModelFromJson(Map json) => UnitContentModel( id: json['id'] as String, - title: json['title'] as String, description: json['description'] as String, - taskSnippetId: json['taskSnippetId'] as String?, - solutionSnippetId: json['solutionSnippetId'] as String?, hints: (json['hints'] as List?)?.map((e) => e as String).toList() ?? [], + solutionSnippetId: json['solutionSnippetId'] as String?, + title: json['title'] as String, + taskSnippetId: json['taskSnippetId'] as String?, ); diff --git a/learning/tour-of-beam/frontend/lib/models/unit_progress.dart b/learning/tour-of-beam/frontend/lib/models/unit_progress.dart index 473c8ae0d4e6d..e3753b81048d1 100644 --- a/learning/tour-of-beam/frontend/lib/models/unit_progress.dart +++ b/learning/tour-of-beam/frontend/lib/models/unit_progress.dart @@ -20,16 +20,20 @@ import 'package:json_annotation/json_annotation.dart'; part 'unit_progress.g.dart'; -@JsonSerializable(createToJson: false) +@JsonSerializable() class UnitProgressModel { final String id; final bool isCompleted; + final String? userSnippetId; const UnitProgressModel({ required this.id, required this.isCompleted, + required this.userSnippetId, }); factory UnitProgressModel.fromJson(Map json) => _$UnitProgressModelFromJson(json); + + Map toJson() => _$UnitProgressModelToJson(this); } diff --git a/learning/tour-of-beam/frontend/lib/models/unit_progress.g.dart b/learning/tour-of-beam/frontend/lib/models/unit_progress.g.dart index c1a773cd66a9c..5c5511604b2be 100644 --- a/learning/tour-of-beam/frontend/lib/models/unit_progress.g.dart +++ b/learning/tour-of-beam/frontend/lib/models/unit_progress.g.dart @@ -10,4 +10,12 @@ UnitProgressModel _$UnitProgressModelFromJson(Map json) => UnitProgressModel( id: json['id'] as String, isCompleted: json['isCompleted'] as bool, + userSnippetId: json['userSnippetId'] as String?, ); + +Map _$UnitProgressModelToJson(UnitProgressModel instance) => + { + 'id': instance.id, + 'isCompleted': instance.isCompleted, + 'userSnippetId': instance.userSnippetId, + }; diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/path.dart b/learning/tour-of-beam/frontend/lib/pages/tour/path.dart index 07dd386bdfcbb..af8452d175487 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/path.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/path.dart @@ -26,7 +26,8 @@ class TourPath extends PagePath { final String sdkId; final List treeIds; - static final _regExp = RegExp(r'^/tour/([a-z]+)((/[-a-zA-Z0-9]+)*)$'); + static final _regExp = + RegExp(r'^/tour/([a-z]+)/?([-a-zA-Z0-9]+(/[-a-zA-Z0-9]+)*)?/?$'); TourPath({ required this.sdkId, @@ -49,10 +50,8 @@ class TourPath extends PagePath { final sdkId = matches[1] ?? (throw Error()); final treeIdsString = matches[2]; - final treeIds = (treeIdsString == null) - ? const [] - // TODO(nausharipov): use RegExp to remove the slash - : treeIdsString.substring(1).split('/'); + final treeIds = + treeIdsString == null ? const [] : treeIdsString.split('/'); return TourPath( sdkId: sdkId, diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/state.dart b/learning/tour-of-beam/frontend/lib/pages/tour/state.dart index 59d88e8e31c74..610347229701b 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/state.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/state.dart @@ -22,22 +22,26 @@ import 'package:app_state/app_state.dart'; import 'package:flutter/widgets.dart'; import 'package:get_it/get_it.dart'; import 'package:playground_components/playground_components.dart'; +import 'package:rate_limiter/rate_limiter.dart'; import '../../auth/notifier.dart'; import '../../cache/unit_content.dart'; import '../../cache/unit_progress.dart'; import '../../config.dart'; +import '../../enums/save_code_status.dart'; +import '../../enums/snippet_type.dart'; import '../../models/unit.dart'; import '../../models/unit_content.dart'; import '../../state.dart'; import 'controllers/content_tree.dart'; -import 'controllers/unit.dart'; import 'path.dart'; class TourNotifier extends ChangeNotifier with PageStateMixin { + static const _saveUserCodeDebounceDuration = Duration(seconds: 2); + Debounce? _saveCodeDebounced; + final ContentTreeController contentTreeController; final PlaygroundController playgroundController; - UnitController? currentUnitController; final _appNotifier = GetIt.instance.get(); final _authNotifier = GetIt.instance.get(); final _unitContentCache = GetIt.instance.get(); @@ -52,11 +56,24 @@ class TourNotifier extends ChangeNotifier with PageStateMixin { initialTreeIds: initialTreeIds, ), playgroundController = _createPlaygroundController(initialSdkId) { + _appNotifier.sdkId ??= initialSdkId; contentTreeController.addListener(_onUnitChanged); _unitContentCache.addListener(_onUnitChanged); _appNotifier.addListener(_onAppNotifierChanged); - _authNotifier.addListener(_onUnitProgressChanged); - _onUnitChanged(); + _authNotifier.addListener(_onAuthChanged); + _saveCodeDebounced = _saveCode.debounced( + _saveUserCodeDebounceDuration, + ); + // setSdk creates snippetEditingController if it doesn't exist. + playgroundController.setSdk(currentSdk); + _listenToCurrentSnippetEditingController(); + unawaited(_onUnitChanged()); + } + + @override + void setStateMap(Map state) { + super.setStateMap(state); + _appNotifier.sdkId = state['sdkId']; } @override @@ -65,106 +82,198 @@ class TourNotifier extends ChangeNotifier with PageStateMixin { treeIds: contentTreeController.treeIds, ); - String? get currentUnitId => currentUnitController?.unitId; + bool get isAuthenticated => _authNotifier.isAuthenticated; + + Sdk get currentSdk => _appNotifier.sdk!; + String? get currentUnitId => _currentUnitContent?.id; UnitContentModel? get currentUnitContent => _currentUnitContent; - bool get doesCurrentUnitHaveSolution => - currentUnitContent?.solutionSnippetId != null; - bool _isShowingSolution = false; - bool get isShowingSolution => _isShowingSolution; - - void toggleShowingSolution() { - if (doesCurrentUnitHaveSolution) { - _isShowingSolution = !_isShowingSolution; - - final snippetId = _isShowingSolution - ? _currentUnitContent?.solutionSnippetId - : _currentUnitContent?.taskSnippetId; - if (snippetId != null) { - // TODO(nausharipov): store/recover - unawaited(_setPlaygroundSnippet(snippetId)); - } - - notifyListeners(); - } - } - void _createCurrentUnitController(String sdkId, String unitId) { - currentUnitController = UnitController( - unitId: unitId, - sdkId: sdkId, - ); - } + bool get hasSolution => currentUnitContent?.solutionSnippetId != null; + bool get isCodeSaved => _unitProgressCache.hasSavedSnippet(currentUnitId); - Future _onUnitProgressChanged() async { - await _unitProgressCache.updateCompletedUnits(); + SnippetType _snippetType = SnippetType.original; + SnippetType get snippetType => _snippetType; + + SaveCodeStatus _saveCodeStatus = SaveCodeStatus.saved; + SaveCodeStatus get saveCodeStatus => _saveCodeStatus; + set saveCodeStatus(SaveCodeStatus saveCodeStatus) { + _saveCodeStatus = saveCodeStatus; + notifyListeners(); } - void _onAppNotifierChanged() { - final sdkId = _appNotifier.sdkId; - if (sdkId != null) { - playgroundController.setSdk(Sdk.parseOrCreate(sdkId)); - contentTreeController.sdkId = sdkId; - _onUnitProgressChanged(); + Future _onAuthChanged() async { + await _unitProgressCache.loadUnitProgress(currentSdk); + // The local changes are preserved if the user signs in. + if (_snippetType != SnippetType.saved || !isAuthenticated) { + await _loadSnippetByType(); } + notifyListeners(); + } + + Future _onAppNotifierChanged() async { + contentTreeController.sdkId = currentSdk.id; + playgroundController.setSdk(currentSdk); + _listenToCurrentSnippetEditingController(); + + await _unitProgressCache.loadUnitProgress(currentSdk); + _trySetSnippetType(SnippetType.saved); + await _loadSnippetByType(); } - void _onUnitChanged() { + Future _onUnitChanged() async { emitPathChanged(); final currentNode = contentTreeController.currentNode; - if (currentNode is UnitModel) { + if (currentNode is! UnitModel) { + await _emptyPlayground(); + } else { final sdk = contentTreeController.sdk; - final content = _unitContentCache.getUnitContent( + final content = await _unitContentCache.getUnitContent( sdk.id, currentNode.id, ); - _createCurrentUnitController(contentTreeController.sdkId, currentNode.id); - _setCurrentUnitContent(content); - } else { - _emptyPlayground(); + _setUnitContent(content); + await _unitProgressCache.loadUnitProgress(currentSdk); + _trySetSnippetType(SnippetType.saved); + await _loadSnippetByType(); } - notifyListeners(); } - Future _setCurrentUnitContent(UnitContentModel? content) async { - if (content == _currentUnitContent) { + void _setUnitContent(UnitContentModel? unitContent) { + if (unitContent == null || unitContent == _currentUnitContent) { return; } + _currentUnitContent = unitContent; + } - _currentUnitContent = content; + // Save user code. - if (content == null) { - return; + Future showSnippetByType(SnippetType snippetType) async { + _trySetSnippetType(snippetType); + await _loadSnippetByType(); + notifyListeners(); + } + + void _listenToCurrentSnippetEditingController() { + playgroundController.snippetEditingController?.addListener( + _onActiveFileControllerChanged, + ); + } + + void _onActiveFileControllerChanged() { + playgroundController + .snippetEditingController?.activeFileController?.codeController + .addListener(_onCodeChanged); + } + + void _onCodeChanged() { + final snippetEditingController = + playgroundController.snippetEditingController!; + final isCodeChanged = + snippetEditingController.activeFileController?.isChanged ?? false; + final snippetFiles = snippetEditingController.getFiles(); + + final doSave = _isSnippetTypeSavable() && + isCodeChanged && + _currentUnitContent != null && + snippetFiles.isNotEmpty; + + if (doSave) { + // Snapshot of sdk and unitId at the moment of editing. + final sdk = currentSdk; + final unitId = currentUnitId; + _saveCodeDebounced?.call([], { + const Symbol('sdk'): sdk, + const Symbol('snippetFiles'): snippetFiles, + const Symbol('unitId'): unitId, + }); } - final taskSnippetId = content.taskSnippetId; - await _setPlaygroundSnippet(taskSnippetId); - _isShowingSolution = false; } - Future _setPlaygroundSnippet(String? snippetId) async { - if (snippetId == null) { - await _emptyPlayground(); - return; + bool _isSnippetTypeSavable() { + return snippetType != SnippetType.solution; + } + + Future _saveCode({ + required Sdk sdk, + required List snippetFiles, + required String unitId, + }) async { + saveCodeStatus = SaveCodeStatus.saving; + try { + await _unitProgressCache.saveSnippet( + sdk: sdk, + snippetFiles: snippetFiles, + snippetType: _snippetType, + unitId: unitId, + ); + saveCodeStatus = SaveCodeStatus.saved; + await _unitProgressCache.loadUnitProgress(currentSdk); + _trySetSnippetType(SnippetType.saved); + } on Exception catch (e) { + print(['Could not save code: ', e]); + _saveCodeStatus = SaveCodeStatus.error; } + } - final selectedSdk = _appNotifier.sdk; - if (selectedSdk != null) { - await playgroundController.examplesLoader.load( - ExamplesLoadingDescriptor( - descriptors: [ - UserSharedExampleLoadingDescriptor( - sdk: selectedSdk, - snippetId: snippetId, - ), - ], - ), + void _trySetSnippetType(SnippetType snippetType) { + if (snippetType == SnippetType.saved && !isCodeSaved) { + _snippetType = SnippetType.original; + } else { + _snippetType = snippetType; + } + notifyListeners(); + } + + Future _loadSnippetByType() async { + final ExampleLoadingDescriptor descriptor; + switch (_snippetType) { + case SnippetType.original: + descriptor = _getStandardOrEmptyDescriptor( + currentSdk, + _currentUnitContent!.taskSnippetId, + ); + break; + case SnippetType.saved: + descriptor = await _unitProgressCache.getSavedDescriptor( + sdk: currentSdk, + unitId: _currentUnitContent!.id, + ); + break; + case SnippetType.solution: + descriptor = _getStandardOrEmptyDescriptor( + currentSdk, + _currentUnitContent!.solutionSnippetId, + ); + break; + } + await playgroundController.examplesLoader.load( + ExamplesLoadingDescriptor( + descriptors: [ + descriptor, + ], + ), + ); + } + + ExampleLoadingDescriptor _getStandardOrEmptyDescriptor( + Sdk sdk, + String? snippetId, + ) { + if (snippetId == null) { + return EmptyExampleLoadingDescriptor( + sdk: currentSdk, ); } + return StandardExampleLoadingDescriptor( + path: snippetId, + sdk: sdk, + ); } // TODO(alexeyinkin): Hide the entire right pane instead. Future _emptyPlayground() async { - await playgroundController.examplesLoader.load( + await playgroundController.examplesLoader.loadIfNew( ExamplesLoadingDescriptor( descriptors: [ EmptyExampleLoadingDescriptor(sdk: contentTreeController.sdk), @@ -173,6 +282,8 @@ class TourNotifier extends ChangeNotifier with PageStateMixin { ); } + // Playground controller. + static PlaygroundController _createPlaygroundController(String initialSdkId) { final exampleRepository = ExampleRepository( client: GrpcExampleClient(url: kApiClientURL), @@ -201,7 +312,7 @@ class TourNotifier extends ChangeNotifier with PageStateMixin { ); unawaited( - playgroundController.examplesLoader.load( + playgroundController.examplesLoader.loadIfNew( ExamplesLoadingDescriptor( descriptors: [ EmptyExampleLoadingDescriptor(sdk: Sdk.parseOrCreate(initialSdkId)), @@ -218,7 +329,13 @@ class TourNotifier extends ChangeNotifier with PageStateMixin { _unitContentCache.removeListener(_onUnitChanged); contentTreeController.removeListener(_onUnitChanged); _appNotifier.removeListener(_onAppNotifierChanged); - _authNotifier.removeListener(_onUnitProgressChanged); + _authNotifier.removeListener(_onAuthChanged); + playgroundController.snippetEditingController + ?.removeListener(_onActiveFileControllerChanged); + // TODO(nausharipov): Use stream events https://github.com/apache/beam/issues/25185 + playgroundController + .snippetEditingController?.activeFileController?.codeController + .removeListener(_onCodeChanged); await super.dispose(); } } diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/binary_progress.dart b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/binary_progress.dart index f562f12182523..db0b174e5daa4 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/binary_progress.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/binary_progress.dart @@ -50,7 +50,10 @@ class BinaryProgressIndicator extends StatelessWidget { ), child: SvgPicture.asset( isCompleted ? Assets.svg.unitProgress100 : Assets.svg.unitProgress0, - color: color, + colorFilter: ColorFilter.mode( + color, + BlendMode.srcIn, + ), ), ); } diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/complete_unit_button.dart b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/complete_unit_button.dart index f29c04a56c5ae..8b13d993e0957 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/complete_unit_button.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/complete_unit_button.dart @@ -28,6 +28,17 @@ class CompleteUnitButton extends StatelessWidget { final TourNotifier tourNotifier; const CompleteUnitButton(this.tourNotifier); + Future _onPressed() async { + final unitId = tourNotifier.currentUnitId; + if (unitId == null) { + return; + } + await GetIt.instance.get().completeUnit( + tourNotifier.currentSdk.id, + unitId, + ); + } + @override Widget build(BuildContext context) { final themeData = Theme.of(context); @@ -40,9 +51,7 @@ class CompleteUnitButton extends StatelessWidget { unitProgressCache.canCompleteUnit(tourNotifier.currentUnitId); final borderColor = canComplete ? themeData.primaryColor : themeData.disabledColor; - final onPressed = canComplete - ? tourNotifier.currentUnitController?.completeUnit - : null; + final onPressed = canComplete ? _onPressed : null; return Flexible( child: OutlinedButton( diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/hints.dart b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/hints.dart index 218624365beff..424ce969d96fe 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/hints.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/hints.dart @@ -64,20 +64,22 @@ class _Popup extends StatelessWidget { child: Container( width: BeamSizes.popupWidth, padding: const EdgeInsets.all(BeamSizes.size16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'pages.tour.hint', - style: Theme.of(context).textTheme.headlineLarge, - ).tr(), - const SizedBox(height: BeamSizes.size8), - TobMarkdown( - padding: EdgeInsets.zero, - data: hint, - ), - ], + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'pages.tour.hint', + style: Theme.of(context).textTheme.headlineLarge, + ).tr(), + const SizedBox(height: BeamSizes.size8), + TobMarkdown( + padding: EdgeInsets.zero, + data: hint, + ), + ], + ), ), ), ); diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/markdown/code_builder.dart b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/markdown/code_builder.dart index c00bfc3f830fc..2eaabc10a506c 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/markdown/code_builder.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/markdown/code_builder.dart @@ -27,13 +27,36 @@ class MarkdownCodeBuilder extends MarkdownElementBuilder { final String textContent = element.textContent; final bool isCodeBlock = textContent.contains('\n'); if (isCodeBlock) { - /// codeblockDecoration is applied - return null; + return _CodeBlock(text: textContent); } return _InlineCode(text: textContent); } } +class _CodeBlock extends StatelessWidget { + final String text; + const _CodeBlock({required this.text}); + + @override + Widget build(BuildContext context) { + final scrollController = ScrollController(); + return Padding( + padding: const EdgeInsets.all(BeamSizes.size4), + child: Scrollbar( + controller: scrollController, + scrollbarOrientation: ScrollbarOrientation.bottom, + thumbVisibility: true, + child: SingleChildScrollView( + controller: scrollController, + padding: const EdgeInsets.all(BeamSizes.size10), + scrollDirection: Axis.horizontal, + child: Text(text), + ), + ), + ); + } +} + class _InlineCode extends StatelessWidget { final String text; const _InlineCode({required this.text}); diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/solution_button.dart b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/solution_button.dart deleted file mode 100644 index dd4f909efc583..0000000000000 --- a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/solution_button.dart +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:playground_components/playground_components.dart'; - -import '../../../assets/assets.gen.dart'; -import '../state.dart'; - -class SolutionButton extends StatelessWidget { - final TourNotifier tourNotifier; - - const SolutionButton({ - required this.tourNotifier, - }); - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: tourNotifier, - builder: (context, child) => TextButton.icon( - style: ButtonStyle( - backgroundColor: MaterialStateProperty.all( - tourNotifier.isShowingSolution - ? Theme.of(context).splashColor - : null, - ), - ), - onPressed: () async { - // TODO(nausharipov): resolve the conflict with save user code - if (tourNotifier.isShowingSolution) { - tourNotifier.toggleShowingSolution(); - } else { - final confirmed = await ConfirmDialog.show( - context: context, - confirmButtonText: 'pages.tour.showSolution'.tr(), - subtitle: 'pages.tour.solveYourself'.tr(), - title: 'pages.tour.solution'.tr(), - ); - if (confirmed) { - tourNotifier.toggleShowingSolution(); - } - } - }, - icon: SvgPicture.asset(Assets.svg.solution), - label: const Text('pages.tour.solution').tr(), - ), - ); - } -} diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/unit_content.dart b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/unit_content.dart index 314c01aa6532d..3b47937a8d437 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/widgets/unit_content.dart +++ b/learning/tour-of-beam/frontend/lib/pages/tour/widgets/unit_content.dart @@ -16,16 +16,19 @@ * limitations under the License. */ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; + import 'package:playground_components/playground_components.dart'; import '../../../constants/sizes.dart'; +import '../../../enums/save_code_status.dart'; +import '../../../enums/snippet_type.dart'; import '../../../models/unit_content.dart'; import '../state.dart'; import 'complete_unit_button.dart'; import 'hints.dart'; import 'markdown/tob_markdown.dart'; -import 'solution_button.dart'; class UnitContentWidget extends StatelessWidget { final TourNotifier tourNotifier; @@ -82,23 +85,25 @@ class _Content extends StatelessWidget { @override Widget build(BuildContext context) { final content = unitContent; - if (content == null) { return Container(); } - if (content.isChallenge) { - return _ChallengeContent( - tourNotifier: tourNotifier, - unitContent: content, - ); - } + return ListView( children: [ - _Title(title: content.title), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _Title(title: content.title), + _Buttons( + unitContent: content, + tourNotifier: tourNotifier, + ), + ], + ), TobMarkdown( - padding: const EdgeInsets.all( - BeamSizes.size12, - ), + padding: const EdgeInsets.all(BeamSizes.size12), data: content.description, ), ], @@ -130,74 +135,135 @@ class _Title extends StatelessWidget { } } -class _ChallengeContent extends StatelessWidget { +class _Buttons extends StatelessWidget { final TourNotifier tourNotifier; final UnitContentModel unitContent; - const _ChallengeContent({ - required this.unitContent, + const _Buttons({ required this.tourNotifier, + required this.unitContent, }); @override Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _Title(title: unitContent.title), - _ChallengeButtons( - unitContent: unitContent, - tourNotifier: tourNotifier, + final hints = unitContent.hints; + + return Padding( + padding: const EdgeInsets.all(BeamSizes.size10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (hints.isNotEmpty) + HintsWidget( + hints: hints, ), - ], - ), - TobMarkdown( - padding: const EdgeInsets.all(BeamSizes.size12), - data: unitContent.description, - ), - ], + _SnippetTypeSwitcher( + tourNotifier: tourNotifier, + unitContent: unitContent, + ), + ], + ), ); } } -class _ChallengeButtons extends StatelessWidget { +class _SnippetTypeSwitcher extends StatelessWidget { final TourNotifier tourNotifier; final UnitContentModel unitContent; - const _ChallengeButtons({ + const _SnippetTypeSwitcher({ required this.tourNotifier, required this.unitContent, }); - static const _buttonPadding = EdgeInsets.only( - top: BeamSizes.size10, - right: BeamSizes.size10, - ); + Future _setSnippetByType(SnippetType snippetType) async { + await tourNotifier.showSnippetByType(snippetType); + } @override Widget build(BuildContext context) { - final hints = unitContent.hints; + return AnimatedBuilder( + animation: tourNotifier, + builder: (context, child) { + final groupValue = tourNotifier.snippetType; - return Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - if (unitContent.isChallenge) - Padding( - padding: _buttonPadding, - child: HintsWidget( - hints: hints, - ), - ), - if (tourNotifier.doesCurrentUnitHaveSolution) - Padding( - padding: _buttonPadding, - child: SolutionButton(tourNotifier: tourNotifier), - ), - ], + return Row( + children: [ + if (tourNotifier.hasSolution) + _SnippetTypeButton( + groupValue: groupValue, + title: 'pages.tour.solution'.tr(), + value: SnippetType.solution, + onChanged: () async { + await _setSnippetByType(SnippetType.solution); + }, + ), + if (tourNotifier.hasSolution || tourNotifier.isCodeSaved) + _SnippetTypeButton( + groupValue: groupValue, + title: unitContent.isChallenge + ? 'pages.tour.assignment'.tr() + : 'pages.tour.example'.tr(), + value: SnippetType.original, + onChanged: () async { + await _setSnippetByType(SnippetType.original); + }, + ), + if (tourNotifier.isCodeSaved) + _SnippetTypeButton( + groupValue: groupValue, + title: tourNotifier.saveCodeStatus == SaveCodeStatus.saving + ? 'pages.tour.saving'.tr() + : 'pages.tour.myCode'.tr(), + value: SnippetType.saved, + onChanged: () async { + await _setSnippetByType(SnippetType.saved); + }, + ), + ], + ); + }, + ); + } +} + +class _SnippetTypeButton extends StatelessWidget { + final SnippetType groupValue; + final VoidCallback onChanged; + final String title; + final SnippetType value; + + const _SnippetTypeButton({ + required this.groupValue, + required this.onChanged, + required this.value, + required this.title, + }); + + @override + Widget build(BuildContext context) { + final isSelected = value == groupValue; + final Color? bgColor; + final Color? fgColor; + final VoidCallback? onPressed; + if (isSelected) { + bgColor = Theme.of(context).splashColor; + fgColor = Theme.of(context).colorScheme.onSurface; + onPressed = null; + } else { + bgColor = null; + fgColor = null; + onPressed = onChanged; + } + + return TextButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(bgColor), + foregroundColor: MaterialStateProperty.all(fgColor), + ), + onPressed: onPressed, + child: Text(title), ); } } diff --git a/learning/tour-of-beam/frontend/lib/pages/welcome/screen.dart b/learning/tour-of-beam/frontend/lib/pages/welcome/screen.dart index 3e9341a6ff5f5..8a022fbd7b88f 100644 --- a/learning/tour-of-beam/frontend/lib/pages/welcome/screen.dart +++ b/learning/tour-of-beam/frontend/lib/pages/welcome/screen.dart @@ -391,7 +391,10 @@ class _ModuleHeader extends StatelessWidget { padding: const EdgeInsets.all(BeamSizes.size4), child: SvgPicture.asset( Assets.svg.welcomeProgress0, - color: BeamColors.grey4, + colorFilter: const ColorFilter.mode( + BeamColors.grey4, + BlendMode.srcIn, + ), ), ), const SizedBox(width: BeamSizes.size16), diff --git a/learning/tour-of-beam/frontend/lib/repositories/client/client.dart b/learning/tour-of-beam/frontend/lib/repositories/client/client.dart index 419962271a02e..bbcb217c9c083 100644 --- a/learning/tour-of-beam/frontend/lib/repositories/client/client.dart +++ b/learning/tour-of-beam/frontend/lib/repositories/client/client.dart @@ -16,6 +16,8 @@ * limitations under the License. */ +import 'package:playground_components/playground_components.dart'; + import '../../models/content_tree.dart'; import '../../models/unit_content.dart'; import '../models/get_sdks_response.dart'; @@ -33,4 +35,10 @@ abstract class TobClient { Future postUnitComplete(String sdkId, String id); Future postDeleteUserProgress(); + + Future postUserCode({ + required List snippetFiles, + required String sdkId, + required String unitId, + }); } diff --git a/learning/tour-of-beam/frontend/lib/repositories/client/cloud_functions_client.dart b/learning/tour-of-beam/frontend/lib/repositories/client/cloud_functions_client.dart index 5138948881cf7..30f61670d8229 100644 --- a/learning/tour-of-beam/frontend/lib/repositories/client/cloud_functions_client.dart +++ b/learning/tour-of-beam/frontend/lib/repositories/client/cloud_functions_client.dart @@ -21,6 +21,7 @@ import 'dart:io'; import 'package:get_it/get_it.dart'; import 'package:http/http.dart' as http; +import 'package:playground_components/playground_components.dart'; import '../../auth/notifier.dart'; import '../../config.dart'; @@ -114,4 +115,29 @@ class CloudFunctionsTobClient extends TobClient { }, ); } + + @override + Future postUserCode({ + required List snippetFiles, + required String sdkId, + required String unitId, + }) async { + final token = await GetIt.instance.get().getToken(); + if (token == null) { + return; + } + + await http.post( + Uri.parse( + '$cloudFunctionsBaseUrl/postUserCode?sdk=$sdkId&id=$unitId', + ), + headers: { + HttpHeaders.authorizationHeader: 'Bearer $token', + }, + body: jsonEncode({ + 'files': snippetFiles.map((file) => file.toJson()).toList(), + 'pipelineOptions': '', + }), + ); + } } diff --git a/learning/tour-of-beam/frontend/lib/pages/tour/controllers/unit.dart b/learning/tour-of-beam/frontend/lib/repositories/user_progress/abstract.dart similarity index 52% rename from learning/tour-of-beam/frontend/lib/pages/tour/controllers/unit.dart rename to learning/tour-of-beam/frontend/lib/repositories/user_progress/abstract.dart index 5331e454ff45f..b1dc96345f740 100644 --- a/learning/tour-of-beam/frontend/lib/pages/tour/controllers/unit.dart +++ b/learning/tour-of-beam/frontend/lib/repositories/user_progress/abstract.dart @@ -16,30 +16,30 @@ * limitations under the License. */ -import 'package:flutter/widgets.dart'; -import 'package:get_it/get_it.dart'; +import 'package:playground_components/playground_components.dart'; -import '../../../cache/unit_progress.dart'; -import '../../../repositories/client/client.dart'; +import '../../enums/snippet_type.dart'; +import '../models/get_user_progress_response.dart'; -class UnitController extends ChangeNotifier { - final String unitId; - final String sdkId; +abstract class AbstractUserProgressRepository { + Future getUserProgress( + Sdk sdk, + ); - UnitController({ - required this.unitId, - required this.sdkId, + Future completeUnit( + String sdkId, + String unitId, + ); + + Future saveUnitSnippet({ + required Sdk sdk, + required List snippetFiles, + required SnippetType snippetType, + required String unitId, }); - Future completeUnit() async { - final client = GetIt.instance.get(); - final unitProgressCache = GetIt.instance.get(); - try { - unitProgressCache.addUpdatingUnitId(unitId); - await client.postUnitComplete(sdkId, unitId); - } finally { - await unitProgressCache.updateCompletedUnits(); - unitProgressCache.clearUpdatingUnitId(unitId); - } - } + Future getSavedDescriptor({ + required Sdk sdk, + required String unitId, + }); } diff --git a/learning/tour-of-beam/frontend/lib/repositories/user_progress/cloud.dart b/learning/tour-of-beam/frontend/lib/repositories/user_progress/cloud.dart new file mode 100644 index 0000000000000..7242208496999 --- /dev/null +++ b/learning/tour-of-beam/frontend/lib/repositories/user_progress/cloud.dart @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:collection/collection.dart'; +import 'package:playground_components/playground_components.dart'; + +import '../../enums/snippet_type.dart'; +import '../client/client.dart'; +import '../models/get_user_progress_response.dart'; +import 'abstract.dart'; + +class CloudUserProgressRepository extends AbstractUserProgressRepository { + CloudUserProgressRepository({ + required this.client, + }); + final TobClient client; + + @override + Future completeUnit(String sdkId, String unitId) async { + await client.postUnitComplete(sdkId, unitId); + } + + @override + Future getSavedDescriptor({ + required Sdk sdk, + required String unitId, + }) async { + final userProgressResponse = await getUserProgress(sdk); + final unitProgress = userProgressResponse?.units.firstWhereOrNull( + (unit) => unit.id == unitId, + ); + final userSnippetId = unitProgress?.userSnippetId; + if (userSnippetId == null) { + return EmptyExampleLoadingDescriptor(sdk: sdk); + } + return UserSharedExampleLoadingDescriptor( + sdk: sdk, + snippetId: userSnippetId, + ); + } + + @override + Future getUserProgress(Sdk sdk) async { + return client.getUserProgress(sdk.id); + } + + @override + Future saveUnitSnippet({ + required Sdk sdk, + required List snippetFiles, + required String unitId, + required SnippetType? snippetType, + }) async { + await client.postUserCode( + snippetFiles: snippetFiles, + sdkId: sdk.id, + unitId: unitId, + ); + } +} diff --git a/learning/tour-of-beam/frontend/lib/repositories/user_progress/hive.dart b/learning/tour-of-beam/frontend/lib/repositories/user_progress/hive.dart new file mode 100644 index 0000000000000..639139e99543f --- /dev/null +++ b/learning/tour-of-beam/frontend/lib/repositories/user_progress/hive.dart @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:convert'; + +import 'package:hive/hive.dart'; +import 'package:playground_components/playground_components.dart'; + +import '../../constants/hive_box_names.dart'; +import '../../enums/snippet_type.dart'; +import '../../models/unit_progress.dart'; +import '../models/get_user_progress_response.dart'; +import 'abstract.dart'; + +class HiveUserProgressRepository extends AbstractUserProgressRepository { + @override + Future completeUnit(String sdkId, String unitId) { + throw UnimplementedError(); + } + + @override + Future getSavedDescriptor({ + required Sdk sdk, + required String unitId, + }) async { + try { + final unitProgressBox = await Hive.openBox( + HiveBoxNames.getSdkBoxName(sdk, HiveBoxNames.unitProgress), + ); + final unitProgress = UnitProgressModel.fromJson( + jsonDecode(unitProgressBox.get(unitId)), + ); + return HiveExampleLoadingDescriptor( + boxName: HiveBoxNames.getSdkBoxName(sdk, HiveBoxNames.snippets), + sdk: sdk, + snippetId: unitProgress.userSnippetId!, + ); + } on Exception { + return EmptyExampleLoadingDescriptor(sdk: sdk); + } + } + + @override + Future getUserProgress(Sdk sdk) async { + final sdkUnitProgressBox = await Hive.openBox( + HiveBoxNames.getSdkBoxName(sdk, HiveBoxNames.unitProgress), + ); + return GetUserProgressResponse.fromJson({ + // TODO(nausharipov): Replace lambda with tear-off when this lands: https://github.com/dart-lang/language/issues/1813 + 'units': sdkUnitProgressBox.values.map((e) => jsonDecode(e)).toList(), + }); + } + + @override + Future saveUnitSnippet({ + required Sdk sdk, + required List snippetFiles, + required SnippetType snippetType, + required String unitId, + }) async { + final snippetsBox = await Hive.openBox( + HiveBoxNames.getSdkBoxName(sdk, HiveBoxNames.snippets), + ); + final snippetId = 'local_${snippetType.name}_$unitId'; + + await _saveUnitProgressIfUnsaved( + sdk: sdk, + unitId: unitId, + userSnippetId: snippetId, + ); + + await snippetsBox.put( + snippetId, + jsonEncode( + Example( + files: snippetFiles, + name: 'name', + sdk: sdk, + type: ExampleType.example, + path: 'path', + ).toJson(), + ), + ); + } + + Future _saveUnitProgressIfUnsaved({ + required Sdk sdk, + required String unitId, + required String userSnippetId, + }) async { + final unitProgressBox = await Hive.openBox( + HiveBoxNames.getSdkBoxName(sdk, HiveBoxNames.unitProgress), + ); + final unitProgressEncoded = unitProgressBox.get(unitId); + if (unitProgressEncoded == null) { + await unitProgressBox.put( + unitId, + jsonEncode( + UnitProgressModel( + id: unitId, + isCompleted: false, + userSnippetId: userSnippetId, + ).toJson(), + ), + ); + } + } +} diff --git a/learning/tour-of-beam/frontend/pubspec.lock b/learning/tour-of-beam/frontend/pubspec.lock index b5896e1fa8a5f..9857bae1b7827 100644 --- a/learning/tour-of-beam/frontend/pubspec.lock +++ b/learning/tour-of-beam/frontend/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + sha256: e440ac42679dfc04bbbefb58ed225c994bc7e07fccc8a68ec7d3631a127e5da9 url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "54.0.0" _flutterfire_internals: dependency: transitive description: name: _flutterfire_internals - sha256: "3ff770dfff04a67b0863dff205a0936784de1b87a5e99b11c693fc10e66a9ce3" + sha256: "64fcb0dbca4386356386c085142fa6e79c00a3326ceaa778a2d25f5d9ba61441" url: "https://pub.dev" source: hosted - version: "1.0.12" + version: "1.0.16" aligned_dialog: dependency: transitive description: @@ -29,18 +29,18 @@ packages: dependency: transitive description: name: analyzer - sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + sha256: "2c2e3721ee9fb36de92faa060f3480c81b23e904352b087e5c64224b1a044427" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "5.6.0" app_state: dependency: "direct main" description: name: app_state - sha256: "4824dc181bb5ba35595af6a9a78c9c96e7e4c58ede164e64cce34c75fabf244a" + sha256: "8f363b17492dccf720cc70e896a367726171bee8dad047acd8f69f2cc2cf7e9c" url: "https://pub.dev" source: hosted - version: "0.9.2" + version: "0.9.3" archive: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: args - sha256: b003c3098049a51720352d219b0bb5f219b60fbfb68e7a4748139a06a5676515 + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.0" async: dependency: transitive description: @@ -85,18 +85,18 @@ packages: dependency: transitive description: name: build - sha256: "29a03af98de60b4eb9136acd56608a54e989f6da238a80af739415b05589d6df" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" build_config: dependency: transitive description: name: build_config - sha256: "5b7355c14258f5e7df24bad1566f7b991de3e54aeacfb94e1a65e5233d9739c1" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" build_daemon: dependency: transitive description: @@ -109,26 +109,26 @@ packages: dependency: transitive description: name: build_resolvers - sha256: "9aae031a54ab0beebc30a888c93e900d15ae2fd8883d031dbfbd5ebdb57f5a4c" + sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95 url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.2.0" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "56942f8114731d1e79942cd981cfef29501937ff1bccf4dbdce0273f31f13640" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: f4d6244cc071ba842c296cb1c4ee1b31596b9f924300647ac7a1445493471a3f + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" url: "https://pub.dev" source: hosted - version: "7.2.3" + version: "7.2.7" built_collection: dependency: transitive description: @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: built_value - sha256: d7a9cd57c215bdf8d502772447aa6b52a8ab3f956d25d5fdea6ef1df2d2dad60 + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" url: "https://pub.dev" source: hosted - version: "8.4.1" + version: "8.4.3" characters: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: checked_yaml - sha256: dd007e4fb8270916820a0d66e24f619266b60773cddd082c6439341645af2659 + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" clock: dependency: transitive description: @@ -181,10 +181,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "43743b95913fd28b95184eb1bed7e4bd85b802b8fad0a52522702dbeda4ee3d5" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.4.0" collection: dependency: "direct main" description: @@ -253,10 +253,18 @@ packages: dependency: transitive description: name: convert - sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + url: "https://pub.dev" + source: hosted + version: "1.6.3" crypto: dependency: transitive description: @@ -277,10 +285,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "8aff82f9b26fd868992e5430335a9d773bfef01e1d852d7ba71bf4c5d9349351" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4" dartx: dependency: transitive description: @@ -373,58 +381,58 @@ packages: dependency: "direct main" description: name: firebase_auth - sha256: "721b90fe1a0966add31b47a490672954ac4fe45cfe721fd8a11ffbf4c166f611" + sha256: "9907d80446466e638dad31c195150b305dffd145dc57610fcd12c72289432143" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "4.2.9" firebase_auth_platform_interface: dependency: "direct main" description: name: firebase_auth_platform_interface - sha256: "325d934e21826b3e7030f5018ef61927e2083b4c4fb25218ddef6ffc0012b717" + sha256: c645fec50b0391aa878288f58fa4fe9762c271380c457aedf5c7c9b718604f68 url: "https://pub.dev" source: hosted - version: "6.11.7" + version: "6.11.11" firebase_auth_web: dependency: transitive description: name: firebase_auth_web - sha256: "1a7fe4aafed9b29229aa1de6910e0631be94633b4a235e739cc2830a0f110361" + sha256: "2dcf2a36852b9091741b4a4047a02e1f2c43a62c6cacec7df573a793a6543e6d" url: "https://pub.dev" source: hosted - version: "5.1.3" + version: "5.2.8" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: c129209ba55f3d4272c89fb4a4994c15bea77fb6de63a82d45fb6bc5c94e4355 + sha256: fe30ac230f12f8836bb97e6e09197340d3c584526825b1746ea362a82e1e43f7 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.7.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: "5fab93f5b354648efa62e7cc829c90efb68c8796eecf87e0888cae2d5f3accd4" + sha256: "5615b30c36f55b2777d0533771deda7e5730e769e5d3cb7fda79e9bed86cfa55" url: "https://pub.dev" source: hosted - version: "4.5.2" + version: "4.5.3" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: "18b35ce111b0a4266abf723c825bcf9d4e2519d13638cc7f06f2a8dd960c75bc" + sha256: "291fbcace608aca6c860652e1358ef89752be8cc3ef227f8bbcd1e62775b833a" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.1" fixnum: dependency: transitive description: name: fixnum - sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -434,10 +442,10 @@ packages: dependency: transitive description: name: flutter_code_editor - sha256: "2e48e2a09c4205991787f299cd101f66f28e6845f882df543ae0f4260f9e2c67" + sha256: a220a7dcd197d793f46f2c2132551128bb41b1ccc08f7afb781223e1b5e400a1 url: "https://pub.dev" source: hosted - version: "0.2.9" + version: "0.2.12" flutter_driver: dependency: transitive description: flutter @@ -492,10 +500,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: "97c5b291b4fd34ae4f55d6a4c05841d4d0ed94952e033c5a6529e1b47b4d2a29" + sha256: b9be7260c1fdbe0090a11d9d356fc2c88e14cf33407fc0c1829d76ab13808035 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.1" flutter_test: dependency: "direct dev" description: flutter @@ -510,18 +518,18 @@ packages: dependency: transitive description: name: fluttertoast - sha256: "7a738eddad04c7b27a1ecfecd12e8ecd4b188cdd2d91c252a02a4aba65838c9d" + sha256: "2f9c4d3f4836421f7067a28f8939814597b27614e021da9d63e5d3fb6e212d25" url: "https://pub.dev" source: hosted - version: "8.1.1" + version: "8.2.1" frontend_server_client: dependency: transitive description: name: frontend_server_client - sha256: "4f4a162323c86ffc1245765cfe138872b8f069deb42f7dbb36115fa27f31469b" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.2.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -539,10 +547,10 @@ packages: dependency: transitive description: name: glob - sha256: c51b4fdfee4d281f49b8c957f1add91b815473597f76bcf07377987f66a55729 + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" google_fonts: dependency: "direct main" description: @@ -551,54 +559,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.3" - google_identity_services_web: - dependency: transitive - description: - name: google_identity_services_web - sha256: "5d9af2f1fa192f2629a266d038ee9307b0abe729a4f1b454dd21b414f5e7d381" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - google_sign_in: - dependency: "direct main" - description: - name: google_sign_in - sha256: "4f7177a6116738b0c54230a864f1d44d5d2bbec3e43b4d00c16735e32bb8e8da" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - google_sign_in_android: - dependency: transitive - description: - name: google_sign_in_android - sha256: "41187ee48f8f3f7588cb932a5ab3cc8c83f354d1d50c750f61b240efac1b33d2" - url: "https://pub.dev" - source: hosted - version: "6.1.4" - google_sign_in_ios: - dependency: transitive - description: - name: google_sign_in_ios - sha256: "1116aff5e87f89837b052a81abe6259be7c4dd418275786864d27b74cb2a4e70" - url: "https://pub.dev" - source: hosted - version: "5.5.1" - google_sign_in_platform_interface: - dependency: transitive - description: - name: google_sign_in_platform_interface - sha256: "61306213c76bb8170c3aa20017df296c0131c24d7f6c0cc7e2eeaeac34c9f457" - url: "https://pub.dev" - source: hosted - version: "2.3.0" - google_sign_in_web: - dependency: transitive - description: - name: google_sign_in_web - sha256: a33778787257c348f1ec8f0ab51bc680af7dc224ad7a71fb5a5d49177dca3c49 - url: "https://pub.dev" - source: hosted - version: "0.11.0" googleapis_auth: dependency: transitive description: @@ -611,18 +571,18 @@ packages: dependency: transitive description: name: graphs - sha256: ae0b3d956ff324c6f8671f08dcb2dbd71c99cdbf2aa3ca63a14190c47aa6679c + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" grpc: dependency: transitive description: name: grpc - sha256: "3e8e04c6277059b66d67951143842097e52bbf3f2c6fca2e67d3607b48d5c3ab" + sha256: a73c16e4f6a4a819be892bb2c73cc1d0b00e36095f69b0738cc91a733e3d27ba url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.0" highlight: dependency: transitive description: @@ -632,13 +592,21 @@ packages: source: hosted version: "0.7.0" hive: - dependency: transitive + dependency: "direct main" description: name: hive sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" url: "https://pub.dev" source: hosted version: "2.2.3" + hive_test: + dependency: transitive + description: + name: hive_test + sha256: dd7a5cf0be7af288566a96180b5d07574023777aa947ef252b69046ec36d8eb2 + url: "https://pub.dev" + source: hosted + version: "1.0.1" http: dependency: "direct main" description: @@ -651,10 +619,10 @@ packages: dependency: transitive description: name: http2 - sha256: feb9fbe4790be90fef454eb930368c40ae56df598b3e9b9c10cc216d68f75720 + sha256: "58805ebc6513eed3b98ee0a455a8357e61d187bf2e0fdc1e53120770f78de258" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.1" http_multi_server: dependency: transitive description: @@ -667,10 +635,10 @@ packages: dependency: transitive description: name: http_parser - sha256: db3060f22889f3d9d55f6a217565486737037eec3609f7f3eca4d0c67ee0d8a0 + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" integration_test: dependency: "direct dev" description: flutter @@ -688,10 +656,10 @@ packages: dependency: transitive description: name: io - sha256: "0d4c73c3653ab85bf696d51a9657604c900a370549196a91f33e4c39af760852" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: @@ -704,18 +672,18 @@ packages: dependency: "direct main" description: name: json_annotation - sha256: "3520fa844009431b5d4491a5a778603520cdc399ab3406332dcc50f93547258c" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.0" json_serializable: dependency: "direct dev" description: name: json_serializable - sha256: "581006a34721ff9b9cbc2ba6aab4c81ee9a9f345e9f046f9feef5732417cfe4b" + sha256: dadc08bd61f72559f938dd08ec20dbfec6c709bba83515085ea943d2078d187a url: "https://pub.dev" source: hosted - version: "6.4.1" + version: "6.6.1" keyed_collection_widgets: dependency: transitive description: @@ -736,10 +704,10 @@ packages: dependency: transitive description: name: logging - sha256: "293ae2d49fd79d4c04944c3a26dfd313382d5f52e821ec57119230ae16031ad4" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.1" markdown: dependency: "direct main" description: @@ -776,10 +744,18 @@ packages: dependency: transitive description: name: mime - sha256: dab22e92b41aa1255ea90ddc4bc2feaf35544fd0728e209638cad041a6e3928a + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.4" + mocktail: + dependency: transitive + description: + name: mocktail + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" + source: hosted + version: "0.3.0" nested: dependency: transitive description: @@ -823,58 +799,50 @@ packages: dependency: transitive description: name: path_provider - sha256: "050e8e85e4b7fecdf2bb3682c1c64c4887a183720c802d323de8a5fd76d372dd" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "833c8bcb182b515cd872c113e29aaaffd29a1c720259dd2f65ab35ed5e0db748" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e url: "https://pub.dev" source: hosted - version: "2.0.17" - path_provider_ios: + version: "2.0.22" + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - sha256: "03d639406f5343478352433f00d3c4394d52dac8df3d847869c5e2333e0bbce8" + name: path_provider_foundation + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 - url: "https://pub.dev" - source: hosted - version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - sha256: "2a97e7fbb7ae9dcd0dfc1220a78e9ec3e71da691912e617e8715ff2a13086ae8" + sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.8" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "27dc7a224fcd07444cb5e0e60423ccacea3e13cf00fc5282ac2c918132da931d" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "999d3dc2ac03ca3f8433018efa40b73558fa4f9759bf8383a217861d120c7d74" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.3" petitparser: dependency: transitive description: @@ -934,18 +902,18 @@ packages: dependency: "direct main" description: name: provider - sha256: "8d7d4c2df46d6a6270a4e10404bfecb18a937e3e00f710c260d0a10415ce6b7b" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver - sha256: "816c1a640e952d213ddd223b3e7aafae08cd9f8e1f6864eed304cc13b0272b07" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.3" pubspec_parse: dependency: transitive description: @@ -954,14 +922,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" - quiver: - dependency: transitive + rate_limiter: + dependency: "direct main" description: - name: quiver - sha256: "93982981971e812c94d4a6fa3a57b89f9ec12b38b6380cd3c1370c3b01e4580e" + name: rate_limiter + sha256: "2bae2e961adedf7fc2e8b0305d30e3a3619baf001d050c6907870c5c6235b559" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "1.0.0" rxdart: dependency: transitive description: @@ -982,50 +950,42 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "76917b7d4b9526b2ba416808a7eb9fb2863c1a09cf63ec85f1453da240fa818a" + sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "853801ce6ba7429ec4e923e37317f32a57c903de50b8c33ffcfbdb7e6f0dd39c" + sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" url: "https://pub.dev" source: hosted - version: "2.0.12" - shared_preferences_ios: + version: "2.0.15" + shared_preferences_foundation: dependency: transitive description: - name: shared_preferences_ios - sha256: "585a14cefec7da8c9c2fb8cd283a3bb726b4155c0952afe6a0caaa7b2272de34" + name: shared_preferences_foundation + sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.3" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "28aefc1261746e7bad3d09799496054beb84e8c4ffcdfed7734e17b4ada459a5" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - sha256: fbb94bf296576f49be37a1496d5951796211a8db0aa22cc0d68c46440dad808c + sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "992f0fdc46d0a3c0ac2e5859f2de0e577bbe51f78a77ee8f357cbe626a2ad32d" + sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" shared_preferences_web: dependency: transitive description: @@ -1038,26 +998,42 @@ packages: dependency: transitive description: name: shared_preferences_windows - sha256: "97f7ab9a7da96d9cf19581f5de520ceb529548498bd6b5e0ccd02d68a0d15eba" + sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.3" shelf: dependency: transitive description: name: shelf - sha256: "8ec607599dd0a78931a5114cdac7d609b6dbbf479a38acc9a6dba024b2a30ea0" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" + source: hosted + version: "1.4.0" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.1.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "6db16374bc3497d21aa0eebe674d3db9fdf82082aac0f04dc7b44e4af5b08afc" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.3" sky_engine: dependency: transitive description: flutter @@ -1067,10 +1043,10 @@ packages: dependency: transitive description: name: source_gen - sha256: "85f8c7d6425dff95475db618404732f034c87fe23efe05478cea50520a2517a3" + sha256: c2bea18c95cfa0276a366270afaa2850b09b4a76db95d546f3d003dcc7011298 url: "https://pub.dev" source: hosted - version: "1.2.5" + version: "1.2.7" source_helper: dependency: transitive description: @@ -1079,6 +1055,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.3" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" source_span: dependency: transitive description: @@ -1107,10 +1099,10 @@ packages: dependency: transitive description: name: stream_transform - sha256: ed464977cb26a1f41537e177e190c67223dbd9f4f683489b6ab2e5d211ec564e + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" string_scanner: dependency: transitive description: @@ -1135,6 +1127,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + test: + dependency: transitive + description: + name: test + sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d + url: "https://pub.dev" + source: hosted + version: "1.22.0" test_api: dependency: transitive description: @@ -1143,30 +1143,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.16" + test_core: + dependency: transitive + description: + name: test_core + sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888" + url: "https://pub.dev" + source: hosted + version: "0.4.20" time: dependency: transitive description: name: time - sha256: "267028bb7b3e87bbfd66876c6389d7101e4b14eb94fe863d3e008e497ca07844" + sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" timing: dependency: transitive description: name: timing - sha256: c386d07d7f5efc613479a7c4d9d64b03710b03cfaa7e8ad5f2bfb295a1f0dfad + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" total_lints: dependency: "direct dev" description: name: total_lints - sha256: "8da9ee8d6a8e7c28e5e25bc6f35fb2102eaa7151044d7fabfa11c293ad8b4281" + sha256: "5424a55034e89a9c6198518356842dfdc33b6f0b4d557071f84d6095e5a9f8ea" url: "https://pub.dev" source: hosted - version: "2.17.4" + version: "2.19.0" tuple: dependency: transitive description: @@ -1187,66 +1195,66 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "4f0d5f9bf7efba3da5a7ff03bd33cc898c84bac978c068e1c94483828e709592" + sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.1.9" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "1ccd353c1bff66b49863527c02759f4d06b92744bd9777c96a00ca6a9e8e1d2f" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" url: "https://pub.dev" source: hosted - version: "6.0.17" + version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "6ba7dddee26c9fae27c9203c424631109d73c8fa26cfa7bc3e35e751cb87f62e" + sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815" url: "https://pub.dev" source: hosted - version: "6.0.17" + version: "6.1.0" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "360fa359ab06bcb4f7c5cd3123a2a9a4d3364d4575d27c4b33468bd4497dd094" + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: a9b3ea9043eabfaadfa3fb89de67a11210d85569086d22b3854484beab8b3978 + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "80b860b31a11ebbcbe51b8fe887efc204f3af91522f3b51bcda4622d276d2120" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "15fd9dbb306d5efce57dcf62dcb1ae045fbf74079ab4464a950e099bf5800deb" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: e3c3b16d3104260c10eea3b0e34272aaa57921f83148b0619f74c2eced9b7ef1 + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.3" url_strategy: dependency: "direct main" description: @@ -1259,26 +1267,26 @@ packages: dependency: transitive description: name: vector_graphics - sha256: "254348b40251c995cf8301ac715486c8cfa0a93b7fdc4dbd495a30f04db1fb44" + sha256: "09562ef5f47aa84f6567495adb6b9cb2a3192b82c352623b8bd00b300d62603b" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: "143c290b762646c696c63be5d976bde7379ea892cb6868ddc5a17cbc56e71411" + sha256: "886e57742644ebed024dc3ade29712e37eea1b03d294fb314c0a3386243fe5a6" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "3190cc26d9ebda686bafb9721bb6a74c6d358700f4fc978a0f2cba6912daff86" + sha256: "5d9010c4a292766c55395b2288532579a85673f8148460d1e233d98ffe10d24e" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.0.1" vector_math: dependency: transitive description: @@ -1299,18 +1307,18 @@ packages: dependency: transitive description: name: watcher - sha256: e42dfcc48f67618344da967b10f62de57e04bae01d9d3af4c2596f3712a88c99 + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: "3a969ddcc204a3e34e863d204b29c0752716f78b6f9cc8235083208d268a4ccd" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" webdriver: dependency: transitive description: @@ -1319,22 +1327,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" + source: hosted + version: "1.2.0" win32: dependency: transitive description: name: win32 - sha256: "6b75ac2ddd42f5c226fdaf4498a2b04071c06f1f2b8f7ab1c3f77cc7f2285ff1" + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "3.1.3" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: "060b6e1c891d956f72b5ac9463466c37cce3fa962a921532fc001e86fe93438e" + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 url: "https://pub.dev" source: hosted - version: "0.2.0+1" + version: "1.0.0" xml: dependency: transitive description: diff --git a/learning/tour-of-beam/frontend/pubspec.yaml b/learning/tour-of-beam/frontend/pubspec.yaml index 34656acecec2f..075c0e7f6d56b 100644 --- a/learning/tour-of-beam/frontend/pubspec.yaml +++ b/learning/tour-of-beam/frontend/pubspec.yaml @@ -24,7 +24,7 @@ version: 0.1.0 environment: sdk: '>=2.19.2 <4.0.0' - flutter: '>=3.3.2' + flutter: '>=3.7.3' dependencies: app_state: ^0.9.2 @@ -41,12 +41,13 @@ dependencies: flutter_svg: ^2.0.1 get_it: ^7.2.0 google_fonts: ^4.0.3 - google_sign_in: ^6.0.0 + hive: ^2.2.3 http: ^0.13.5 json_annotation: ^4.7.0 markdown: ^7.0.1 playground_components: { path: ../../../playground/frontend/playground_components } provider: ^6.0.3 + rate_limiter: ^1.0.0 shared_preferences: ^2.0.15 url_launcher: ^6.1.5 url_strategy: ^0.2.0 diff --git a/playground/frontend/lib/controllers/factories.dart b/playground/frontend/lib/controllers/factories.dart index 396025c6ae484..92863c18bb739 100644 --- a/playground/frontend/lib/controllers/factories.dart +++ b/playground/frontend/lib/controllers/factories.dart @@ -54,7 +54,7 @@ Future _loadExamples( ExamplesLoadingDescriptor descriptor, ) async { try { - await controller.examplesLoader.load(descriptor); + await controller.examplesLoader.loadIfNew(descriptor); } on Exception catch (ex) { PlaygroundComponents.toastNotifier.addException(ex); diff --git a/playground/frontend/lib/modules/messages/handlers/set_content_message_handler.dart b/playground/frontend/lib/modules/messages/handlers/set_content_message_handler.dart index 6a807e2069386..ce482f07c097c 100644 --- a/playground/frontend/lib/modules/messages/handlers/set_content_message_handler.dart +++ b/playground/frontend/lib/modules/messages/handlers/set_content_message_handler.dart @@ -46,7 +46,7 @@ class SetContentMessageHandler extends AbstractMessageHandler { final descriptor = message.descriptor; try { - await playgroundController.examplesLoader.load(descriptor); + await playgroundController.examplesLoader.loadIfNew(descriptor); } on Exception catch (ex) { PlaygroundComponents.toastNotifier.addException(ex); diff --git a/playground/frontend/playground_components/lib/playground_components.dart b/playground/frontend/playground_components/lib/playground_components.dart index af9f05a668712..a3da2835ced15 100644 --- a/playground/frontend/playground_components/lib/playground_components.dart +++ b/playground/frontend/playground_components/lib/playground_components.dart @@ -34,6 +34,7 @@ export 'src/models/example_loading_descriptors/content_example_loading_descripto export 'src/models/example_loading_descriptors/empty_example_loading_descriptor.dart'; export 'src/models/example_loading_descriptors/example_loading_descriptor.dart'; export 'src/models/example_loading_descriptors/examples_loading_descriptor.dart'; +export 'src/models/example_loading_descriptors/hive_example_loading_descriptor.dart'; export 'src/models/example_loading_descriptors/http_example_loading_descriptor.dart'; export 'src/models/example_loading_descriptors/standard_example_loading_descriptor.dart'; export 'src/models/example_loading_descriptors/user_shared_example_loading_descriptor.dart'; diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart index 75342c3ec0fe9..5a52659caf50f 100644 --- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart +++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/examples_loader.dart @@ -31,6 +31,7 @@ import 'content_example_loader.dart'; import 'empty_example_loader.dart'; import 'example_loader.dart'; import 'example_loader_factory.dart'; +import 'hive_example_loader.dart'; import 'http_example_loader.dart'; import 'standard_example_loader.dart'; import 'user_shared_example_loader.dart'; @@ -44,6 +45,7 @@ class ExamplesLoader { defaultFactory.add(CatalogDefaultExampleLoader.new); defaultFactory.add(ContentExampleLoader.new); defaultFactory.add(EmptyExampleLoader.new); + defaultFactory.add(HiveExampleLoader.new); defaultFactory.add(HttpExampleLoader.new); defaultFactory.add(StandardExampleLoader.new); defaultFactory.add(UserSharedExampleLoader.new); @@ -56,11 +58,14 @@ class ExamplesLoader { /// Loads examples from [descriptor]'s immediate list. /// /// Sets empty editor for SDKs of failed examples. - Future load(ExamplesLoadingDescriptor descriptor) async { + Future loadIfNew(ExamplesLoadingDescriptor descriptor) async { if (_descriptor == descriptor) { return; } + await load(descriptor); + } + Future load(ExamplesLoadingDescriptor descriptor) async { _descriptor = descriptor; final loaders = descriptor.descriptors.map(_createLoader).whereNotNull(); diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/hive_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/hive_example_loader.dart new file mode 100644 index 0000000000000..7f394cfa606d0 --- /dev/null +++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/hive_example_loader.dart @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:convert'; + +import 'package:hive/hive.dart'; + +import '../../cache/example_cache.dart'; +import '../../models/example.dart'; +import '../../models/example_loading_descriptors/hive_example_loading_descriptor.dart'; +import '../../models/sdk.dart'; +import 'example_loader.dart'; + +class HiveExampleLoader extends ExampleLoader { + @override + final HiveExampleLoadingDescriptor descriptor; + + final ExampleCache exampleCache; + + HiveExampleLoader({ + required this.descriptor, + required this.exampleCache, + }); + + @override + Sdk? get sdk => descriptor.sdk; + + @override + Future get future async { + final box = await Hive.openBox(descriptor.boxName); + final Map map = jsonDecode(box.get(descriptor.snippetId)); + return Example.fromJson(map); + } +} diff --git a/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart b/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart index 0afb6828f9b78..2d62e528dbf33 100644 --- a/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart +++ b/playground/frontend/playground_components/lib/src/controllers/example_loaders/standard_example_loader.dart @@ -20,7 +20,6 @@ import 'dart:async'; import '../../cache/example_cache.dart'; import '../../models/example.dart'; -import '../../models/example_base.dart'; import '../../models/example_loading_descriptors/standard_example_loading_descriptor.dart'; import '../../models/sdk.dart'; import 'example_loader.dart'; @@ -35,10 +34,9 @@ class StandardExampleLoader extends ExampleLoader { final ExampleCache exampleCache; final _completer = Completer(); - Sdk? _sdk; @override - Sdk? get sdk => _sdk; + Sdk? get sdk => descriptor.sdk; @override Future get future => _completer.future; @@ -52,12 +50,10 @@ class StandardExampleLoader extends ExampleLoader { Future _load() async { try { - final example = await _loadExampleBase(); - - if (example == null) { - _completer.completeError(Exception('Example not found: $descriptor')); - return; - } + final example = await exampleCache.getPrecompiledObject( + descriptor.path, + descriptor.sdk, + ); _completer.complete( exampleCache.loadExampleInfo(example), @@ -69,14 +65,4 @@ class StandardExampleLoader extends ExampleLoader { return; } } - - Future _loadExampleBase() async { - _sdk = Sdk.tryParseExamplePath(descriptor.path); - - if (_sdk == null) { - return null; - } - - return exampleCache.getPrecompiledObject(descriptor.path, _sdk!); - } } diff --git a/playground/frontend/playground_components/lib/src/models/dataset.dart b/playground/frontend/playground_components/lib/src/models/dataset.dart index 5ec79d29112e6..b51ba85ed1c6e 100644 --- a/playground/frontend/playground_components/lib/src/models/dataset.dart +++ b/playground/frontend/playground_components/lib/src/models/dataset.dart @@ -16,8 +16,13 @@ * limitations under the License. */ +import 'package:json_annotation/json_annotation.dart'; + import '../enums/emulator_type.dart'; +part 'dataset.g.dart'; + +@JsonSerializable() class Dataset { final EmulatorType? type; final Map options; @@ -28,4 +33,9 @@ class Dataset { required this.options, required this.datasetPath, }); + + factory Dataset.fromJson(Map json) => + _$DatasetFromJson(json); + + Map toJson() => _$DatasetToJson(this); } diff --git a/playground/frontend/playground_components/lib/src/models/dataset.g.dart b/playground/frontend/playground_components/lib/src/models/dataset.g.dart new file mode 100644 index 0000000000000..85256b1d5d83b --- /dev/null +++ b/playground/frontend/playground_components/lib/src/models/dataset.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'dataset.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Dataset _$DatasetFromJson(Map json) => Dataset( + type: $enumDecodeNullable(_$EmulatorTypeEnumMap, json['type']), + options: Map.from(json['options'] as Map), + datasetPath: json['datasetPath'] as String, + ); + +Map _$DatasetToJson(Dataset instance) => { + 'type': _$EmulatorTypeEnumMap[instance.type], + 'options': instance.options, + 'datasetPath': instance.datasetPath, + }; + +const _$EmulatorTypeEnumMap = { + EmulatorType.kafka: 'kafka', +}; diff --git a/playground/frontend/playground_components/lib/src/models/example.dart b/playground/frontend/playground_components/lib/src/models/example.dart index 97ad54bf8b1c9..85858e8757177 100644 --- a/playground/frontend/playground_components/lib/src/models/example.dart +++ b/playground/frontend/playground_components/lib/src/models/example.dart @@ -16,11 +16,19 @@ * limitations under the License. */ +import 'package:json_annotation/json_annotation.dart'; + +import '../enums/complexity.dart'; +import 'dataset.dart'; import 'example_base.dart'; +import 'example_view_options.dart'; import 'sdk.dart'; import 'snippet_file.dart'; +part 'example.g.dart'; + /// A [ExampleBase] that also has all large fields fetched. +@JsonSerializable() class Example extends ExampleBase { final List files; final String? graph; @@ -48,6 +56,12 @@ class Example extends ExampleBase { super.viewOptions, }); + factory Example.fromJson(Map json) => + _$ExampleFromJson(json); + + @override + Map toJson() => _$ExampleToJson(this); + Example.fromBase( ExampleBase example, { required this.files, diff --git a/playground/frontend/playground_components/lib/src/models/example.g.dart b/playground/frontend/playground_components/lib/src/models/example.g.dart new file mode 100644 index 0000000000000..f46c32c1d0d44 --- /dev/null +++ b/playground/frontend/playground_components/lib/src/models/example.g.dart @@ -0,0 +1,72 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'example.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Example _$ExampleFromJson(Map json) => Example( + files: (json['files'] as List) + .map((e) => SnippetFile.fromJson(e as Map)) + .toList(), + name: json['name'] as String, + sdk: Sdk.fromJson(json['sdk'] as Map), + type: $enumDecode(_$ExampleTypeEnumMap, json['type']), + path: json['path'] as String, + complexity: $enumDecodeNullable(_$ComplexityEnumMap, json['complexity']), + contextLine: json['contextLine'] as int? ?? 1, + datasets: (json['datasets'] as List?) + ?.map((e) => Dataset.fromJson(e as Map)) + .toList() ?? + const [], + description: json['description'] as String? ?? '', + graph: json['graph'] as String?, + isMultiFile: json['isMultiFile'] as bool? ?? false, + logs: json['logs'] as String?, + outputs: json['outputs'] as String?, + pipelineOptions: json['pipelineOptions'] as String? ?? '', + tags: + (json['tags'] as List?)?.map((e) => e as String).toList() ?? + const [], + urlNotebook: json['urlNotebook'] as String?, + urlVcs: json['urlVcs'] as String?, + viewOptions: json['viewOptions'] == null + ? ExampleViewOptions.empty + : ExampleViewOptions.fromJson( + json['viewOptions'] as Map), + ); + +Map _$ExampleToJson(Example instance) => { + 'complexity': _$ComplexityEnumMap[instance.complexity], + 'contextLine': instance.contextLine, + 'datasets': instance.datasets, + 'description': instance.description, + 'isMultiFile': instance.isMultiFile, + 'name': instance.name, + 'path': instance.path, + 'pipelineOptions': instance.pipelineOptions, + 'sdk': instance.sdk, + 'tags': instance.tags, + 'type': _$ExampleTypeEnumMap[instance.type]!, + 'urlNotebook': instance.urlNotebook, + 'urlVcs': instance.urlVcs, + 'viewOptions': instance.viewOptions, + 'files': instance.files, + 'graph': instance.graph, + 'logs': instance.logs, + 'outputs': instance.outputs, + }; + +const _$ExampleTypeEnumMap = { + ExampleType.all: 'all', + ExampleType.example: 'example', + ExampleType.kata: 'kata', + ExampleType.test: 'test', +}; + +const _$ComplexityEnumMap = { + Complexity.basic: 'BASIC', + Complexity.medium: 'MEDIUM', + Complexity.advanced: 'ADVANCED', +}; diff --git a/playground/frontend/playground_components/lib/src/models/example_base.dart b/playground/frontend/playground_components/lib/src/models/example_base.dart index 5753c5eaa81db..238cb621a8f88 100644 --- a/playground/frontend/playground_components/lib/src/models/example_base.dart +++ b/playground/frontend/playground_components/lib/src/models/example_base.dart @@ -17,6 +17,7 @@ */ import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; import '../enums/complexity.dart'; import '../repositories/example_repository.dart'; @@ -24,6 +25,8 @@ import 'dataset.dart'; import 'example_view_options.dart'; import 'sdk.dart'; +part 'example_base.g.dart'; + enum ExampleType { all, example, @@ -49,6 +52,7 @@ extension ExampleTypeToString on ExampleType { /// An example's basic info that does not contain source code /// and other large fields. /// These objects are fetched as lists from [ExampleRepository]. +@JsonSerializable() class ExampleBase with Comparable, EquatableMixin { final Complexity? complexity; @@ -84,6 +88,11 @@ class ExampleBase with Comparable, EquatableMixin { this.viewOptions = ExampleViewOptions.empty, }); + factory ExampleBase.fromJson(Map json) => + _$ExampleBaseFromJson(json); + + Map toJson() => _$ExampleBaseToJson(this); + // TODO(alexeyinkin): Use all fields, https://github.com/apache/beam/issues/23979 @override List get props => [path]; diff --git a/playground/frontend/playground_components/lib/src/models/example_base.g.dart b/playground/frontend/playground_components/lib/src/models/example_base.g.dart new file mode 100644 index 0000000000000..0f18242faf2c0 --- /dev/null +++ b/playground/frontend/playground_components/lib/src/models/example_base.g.dart @@ -0,0 +1,63 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'example_base.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ExampleBase _$ExampleBaseFromJson(Map json) => ExampleBase( + name: json['name'] as String, + path: json['path'] as String, + sdk: Sdk.fromJson(json['sdk'] as Map), + type: $enumDecode(_$ExampleTypeEnumMap, json['type']), + complexity: $enumDecodeNullable(_$ComplexityEnumMap, json['complexity']), + contextLine: json['contextLine'] as int? ?? 1, + datasets: (json['datasets'] as List?) + ?.map((e) => Dataset.fromJson(e as Map)) + .toList() ?? + const [], + description: json['description'] as String? ?? '', + isMultiFile: json['isMultiFile'] as bool? ?? false, + pipelineOptions: json['pipelineOptions'] as String? ?? '', + tags: + (json['tags'] as List?)?.map((e) => e as String).toList() ?? + const [], + urlNotebook: json['urlNotebook'] as String?, + urlVcs: json['urlVcs'] as String?, + viewOptions: json['viewOptions'] == null + ? ExampleViewOptions.empty + : ExampleViewOptions.fromJson( + json['viewOptions'] as Map), + ); + +Map _$ExampleBaseToJson(ExampleBase instance) => + { + 'complexity': _$ComplexityEnumMap[instance.complexity], + 'contextLine': instance.contextLine, + 'datasets': instance.datasets, + 'description': instance.description, + 'isMultiFile': instance.isMultiFile, + 'name': instance.name, + 'path': instance.path, + 'pipelineOptions': instance.pipelineOptions, + 'sdk': instance.sdk, + 'tags': instance.tags, + 'type': _$ExampleTypeEnumMap[instance.type]!, + 'urlNotebook': instance.urlNotebook, + 'urlVcs': instance.urlVcs, + 'viewOptions': instance.viewOptions, + }; + +const _$ExampleTypeEnumMap = { + ExampleType.all: 'all', + ExampleType.example: 'example', + ExampleType.kata: 'kata', + ExampleType.test: 'test', +}; + +const _$ComplexityEnumMap = { + Complexity.basic: 'BASIC', + Complexity.medium: 'MEDIUM', + Complexity.advanced: 'ADVANCED', +}; diff --git a/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/hive_example_loading_descriptor.dart b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/hive_example_loading_descriptor.dart new file mode 100644 index 0000000000000..f69a9e505914c --- /dev/null +++ b/playground/frontend/playground_components/lib/src/models/example_loading_descriptors/hive_example_loading_descriptor.dart @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '../example_view_options.dart'; +import '../sdk.dart'; +import 'example_loading_descriptor.dart'; + +/// Describes a loadable example saved in Hive. +class HiveExampleLoadingDescriptor extends ExampleLoadingDescriptor { + final String boxName; + final Sdk sdk; + final String snippetId; + + const HiveExampleLoadingDescriptor({ + required this.boxName, + required this.sdk, + required this.snippetId, + super.viewOptions, + }); + + @override + List get props => [ + boxName, + sdk.id, + snippetId, + viewOptions, + ]; + + @override + HiveExampleLoadingDescriptor copyWithoutViewOptions() => + HiveExampleLoadingDescriptor( + boxName: boxName, + sdk: sdk, + snippetId: snippetId, + ); + + @override + Map toJson() => { + 'boxName': boxName, + 'sdk': sdk.id, + 'shared': snippetId, + ...viewOptions.toShortMap(), + }; + + static HiveExampleLoadingDescriptor? tryParse( + Map map, + ) { + final boxName = map['boxName']; + final sdkId = map['sdk']; + final snippetId = map['shared']; + + if (sdkId == null || snippetId == null) { + return null; + } + + return HiveExampleLoadingDescriptor( + boxName: boxName, + sdk: Sdk.parseOrCreate(sdkId), + snippetId: snippetId, + viewOptions: ExampleViewOptions.fromShortMap(map), + ); + } +} diff --git a/playground/frontend/playground_components/lib/src/models/example_view_options.dart b/playground/frontend/playground_components/lib/src/models/example_view_options.dart index be1d157534170..54ced794fc207 100644 --- a/playground/frontend/playground_components/lib/src/models/example_view_options.dart +++ b/playground/frontend/playground_components/lib/src/models/example_view_options.dart @@ -17,9 +17,13 @@ */ import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; import '../util/string.dart'; +part 'example_view_options.g.dart'; + +@JsonSerializable() class ExampleViewOptions with EquatableMixin { final bool foldCommentAtLineZero; final bool foldImports; @@ -35,6 +39,16 @@ class ExampleViewOptions with EquatableMixin { this.foldImports = true, }); + /// Parses a fully normalized map. + factory ExampleViewOptions.fromJson(Map json) => + _$ExampleViewOptionsFromJson(json); + + Map toJson() => _$ExampleViewOptionsToJson(this); + + /// Parses a simplified map that comes from a URL. + /// + /// This map has CSV strings instead of JSON arrays + /// and cannot override folding parameters' defaults. factory ExampleViewOptions.fromShortMap(Map map) { return ExampleViewOptions( readOnlySectionNames: _split(map['readonly']), diff --git a/playground/frontend/playground_components/lib/src/models/example_view_options.g.dart b/playground/frontend/playground_components/lib/src/models/example_view_options.g.dart new file mode 100644 index 0000000000000..e0b8d580862b8 --- /dev/null +++ b/playground/frontend/playground_components/lib/src/models/example_view_options.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'example_view_options.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ExampleViewOptions _$ExampleViewOptionsFromJson(Map json) => + ExampleViewOptions( + readOnlySectionNames: (json['readOnlySectionNames'] as List) + .map((e) => e as String) + .toList(), + showSectionNames: (json['showSectionNames'] as List) + .map((e) => e as String) + .toList(), + unfoldSectionNames: (json['unfoldSectionNames'] as List) + .map((e) => e as String) + .toList(), + foldCommentAtLineZero: json['foldCommentAtLineZero'] as bool? ?? true, + foldImports: json['foldImports'] as bool? ?? true, + ); + +Map _$ExampleViewOptionsToJson(ExampleViewOptions instance) => + { + 'foldCommentAtLineZero': instance.foldCommentAtLineZero, + 'foldImports': instance.foldImports, + 'readOnlySectionNames': instance.readOnlySectionNames, + 'showSectionNames': instance.showSectionNames, + 'unfoldSectionNames': instance.unfoldSectionNames, + }; diff --git a/playground/frontend/playground_components/lib/src/models/sdk.dart b/playground/frontend/playground_components/lib/src/models/sdk.dart index e6c98bbaf6a26..6250e1da1a4fa 100644 --- a/playground/frontend/playground_components/lib/src/models/sdk.dart +++ b/playground/frontend/playground_components/lib/src/models/sdk.dart @@ -27,7 +27,7 @@ import 'package:json_annotation/json_annotation.dart'; part 'sdk.g.dart'; -@JsonSerializable(createToJson: false) +@JsonSerializable() class Sdk with EquatableMixin { final String id; final String title; @@ -59,32 +59,6 @@ class Sdk with EquatableMixin { title, ]; - /// A temporary solution while we wait for the backend to add - /// sdk in example responses. - static Sdk? tryParseExamplePath(String? path) { - if (path == null) { - return null; - } - - if (path.startsWith('SDK_JAVA')) { - return java; - } - - if (path.startsWith('SDK_GO')) { - return go; - } - - if (path.startsWith('SDK_PYTHON')) { - return python; - } - - if (path.startsWith('SDK_SCIO')) { - return scio; - } - - return null; - } - static Sdk? tryParse(Object? value) { if (value is! String) { return null; @@ -102,6 +76,7 @@ class Sdk with EquatableMixin { Mode? get highlightMode => _idToHighlightMode[id]; - factory Sdk.fromJson(Map json) => - _$SdkFromJson(json); + factory Sdk.fromJson(Map json) => _$SdkFromJson(json); + + Map toJson() => _$SdkToJson(this); } diff --git a/playground/frontend/playground_components/lib/src/models/sdk.g.dart b/playground/frontend/playground_components/lib/src/models/sdk.g.dart index 63b1d0978fc67..d43ed04f63a7b 100644 --- a/playground/frontend/playground_components/lib/src/models/sdk.g.dart +++ b/playground/frontend/playground_components/lib/src/models/sdk.g.dart @@ -10,3 +10,8 @@ Sdk _$SdkFromJson(Map json) => Sdk( id: json['id'] as String, title: json['title'] as String, ); + +Map _$SdkToJson(Sdk instance) => { + 'id': instance.id, + 'title': instance.title, + }; diff --git a/playground/frontend/playground_components/lib/src/theme/theme.dart b/playground/frontend/playground_components/lib/src/theme/theme.dart index 4b87f5f1ca626..5a8ba06109ff2 100644 --- a/playground/frontend/playground_components/lib/src/theme/theme.dart +++ b/playground/frontend/playground_components/lib/src/theme/theme.dart @@ -129,6 +129,7 @@ class BeamThemeExtension extends ThemeExtension { final kLightTheme = ThemeData( brightness: Brightness.light, appBarTheme: _getAppBarTheme(BeamLightThemeColors.secondaryBackground), + // TODO(nausharipov): Migrate to Material 3: https://github.com/apache/beam/issues/24610 backgroundColor: BeamLightThemeColors.primaryBackground, canvasColor: BeamLightThemeColors.primaryBackground, dividerColor: BeamLightThemeColors.grey, diff --git a/playground/frontend/playground_components/pubspec.yaml b/playground/frontend/playground_components/pubspec.yaml index a7c35d9ffa15b..7b8d72bc8fcbb 100644 --- a/playground/frontend/playground_components/pubspec.yaml +++ b/playground/frontend/playground_components/pubspec.yaml @@ -35,7 +35,7 @@ dependencies: enum_map: ^0.2.1 equatable: ^2.0.5 flutter: { sdk: flutter } - flutter_code_editor: ^0.2.12 + flutter_code_editor: ^0.2.14 flutter_markdown: ^0.6.12 flutter_svg: ^2.0.1 fluttertoast: ^8.1.1 @@ -43,6 +43,8 @@ dependencies: google_fonts: ^4.0.3 grpc: ^3.0.2 highlight: ^0.7.0 + hive: ^2.2.3 + hive_test: ^1.0.1 http: ^0.13.5 json_annotation: ^4.7.0 keyed_collection_widgets: ^0.4.3 diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.dart index 705d2961946f2..67f20cf13fb0e 100644 --- a/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.dart +++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/examples_loader_test.dart @@ -95,7 +95,7 @@ void main() async { }, ); - await examplesLoader.load(descriptor); + await examplesLoader.loadIfNew(descriptor); expect(setExampleTrue, [Sdk.go.id, Sdk.python.id]); expect(setExampleFalse, []); @@ -113,7 +113,7 @@ void main() async { initialSdk: Sdk.python, ); - await examplesLoader.load(descriptor); + await examplesLoader.loadIfNew(descriptor); expect(setExampleTrue, [Sdk.python.id]); expect(setExampleFalse, [Sdk.go.id]); @@ -132,7 +132,7 @@ void main() async { ); try { - await examplesLoader.load(descriptor); + await examplesLoader.loadIfNew(descriptor); } on ExampleLoadingException catch (ex) { thrown = ex; } diff --git a/playground/frontend/playground_components/test/src/controllers/example_loaders/hive_example_loader_test.dart b/playground/frontend/playground_components/test/src/controllers/example_loaders/hive_example_loader_test.dart new file mode 100644 index 0000000000000..7975bda8d594d --- /dev/null +++ b/playground/frontend/playground_components/test/src/controllers/example_loaders/hive_example_loader_test.dart @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:hive/hive.dart'; +import 'package:hive_test/hive_test.dart'; +import 'package:playground_components/playground_components.dart'; +import 'package:playground_components/src/controllers/example_loaders/hive_example_loader.dart'; + +import '../../common/example_cache.mocks.dart'; + +const _example = Example( + files: [], + name: 'name', + sdk: Sdk.go, + type: ExampleType.example, + path: 'path', +); + +void main() { + test('HiveExampleLoader loads locally stored example', () async { + await setUpTestHive(); + + const descriptor = HiveExampleLoadingDescriptor( + sdk: Sdk.go, + boxName: 'boxName', + snippetId: 'snippetId', + ); + + final box = await Hive.openBox(descriptor.boxName); + await box.put(descriptor.snippetId, jsonEncode(_example.toJson())); + + final loader = HiveExampleLoader( + descriptor: descriptor, + exampleCache: MockExampleCache(), + ); + + final exampleFromHive = await loader.future; + + expect(exampleFromHive.name, _example.name); + expect(exampleFromHive.sdk.id, _example.sdk.id); + + await tearDownTestHive(); + }); +} diff --git a/playground/frontend/playground_components/test/src/controllers/playground_controller_test.dart b/playground/frontend/playground_components/test/src/controllers/playground_controller_test.dart index 44d1a3bb05eb4..696b887d7f14f 100644 --- a/playground/frontend/playground_components/test/src/controllers/playground_controller_test.dart +++ b/playground/frontend/playground_components/test/src/controllers/playground_controller_test.dart @@ -33,7 +33,7 @@ Future main() async { late PlaygroundController controller; final mockExamplesLoader = MockExamplesLoader(); - when(mockExamplesLoader.load(any)).thenAnswer((_) async => 1); + when(mockExamplesLoader.loadIfNew(any)).thenAnswer((_) async => 1); setUp(() { controller = PlaygroundController( diff --git a/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart b/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart index 6ab8b1e9dbb75..ae867f7c18d81 100644 --- a/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart +++ b/playground/frontend/playground_components/test/src/controllers/playground_controller_test.mocks.dart @@ -94,6 +94,16 @@ class MockExamplesLoader extends _i1.Mock implements _i5.ExamplesLoader { returnValueForMissingStub: null, ); @override + _i7.Future loadIfNew(_i8.ExamplesLoadingDescriptor? descriptor) => + (super.noSuchMethod( + Invocation.method( + #loadIfNew, + [descriptor], + ), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) as _i7.Future); + @override _i7.Future load(_i8.ExamplesLoadingDescriptor? descriptor) => (super.noSuchMethod( Invocation.method( diff --git a/playground/frontend/playground_components/test/src/models/example_loading_descriptors/hive_example_loading_descriptor_test.dart b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/hive_example_loading_descriptor_test.dart new file mode 100644 index 0000000000000..fdb9863fd2dd1 --- /dev/null +++ b/playground/frontend/playground_components/test/src/models/example_loading_descriptors/hive_example_loading_descriptor_test.dart @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'package:flutter_test/flutter_test.dart'; +import 'package:playground_components/src/models/example_loading_descriptors/hive_example_loading_descriptor.dart'; +import 'package:playground_components/src/models/sdk.dart'; + +import 'common.dart'; + +void main() { + group('HiveExampleLoadingDescriptor', () { + const descriptor = HiveExampleLoadingDescriptor( + boxName: 'boxName', + sdk: Sdk.go, + snippetId: 'snippetId', + viewOptions: viewOptions, + ); + + test('toJson -> tryParse', () { + final map = descriptor.toJson(); + final parsed = HiveExampleLoadingDescriptor.tryParse(map); + + expect(parsed, descriptor); + }); + + test('copyWithoutViewOptions', () { + expect( + descriptor.copyWithoutViewOptions(), + HiveExampleLoadingDescriptor( + boxName: descriptor.boxName, + sdk: descriptor.sdk, + snippetId: descriptor.snippetId, + ), + ); + }); + }); +} diff --git a/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart b/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart index d341e3c0566cd..60b85e0fa4b83 100644 --- a/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart +++ b/playground/frontend/test/pages/playground/states/example_selector_state_test.mocks.dart @@ -64,6 +64,16 @@ class MockExamplesLoader extends _i1.Mock implements _i3.ExamplesLoader { returnValueForMissingStub: null, ); @override + _i5.Future loadIfNew(_i6.ExamplesLoadingDescriptor? descriptor) => + (super.noSuchMethod( + Invocation.method( + #loadIfNew, + [descriptor], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + @override _i5.Future load(_i6.ExamplesLoadingDescriptor? descriptor) => (super.noSuchMethod( Invocation.method(