diff --git a/.env.sample b/.env.sample deleted file mode 100644 index db332bb..0000000 --- a/.env.sample +++ /dev/null @@ -1,2 +0,0 @@ -SENTRY_DSN= -ENABLE_SENTRY=false \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6602d4d..2f479f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,50 +1,25 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ +# Xcode user data +xcuserdata/ +*.xcuserstate + +# Build artifacts +DerivedData/ +build/ +*.ipa +*.dSYM.zip +*.dSYM + +# Swift Package Manager .build/ -.buildlog/ -.history -.svn/ .swiftpm/ -migrate_working_dir/ -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ +# CocoaPods +Pods/ -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ +# macOS +.DS_Store +.DS_Store? +._* -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release - -# Env file -.env -android/app/.cxx -android/build/reports/problems +# VS Code +.vscode/ diff --git a/.metadata b/.metadata deleted file mode 100644 index fc44c8e..0000000 --- a/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "00b0c91f06209d9e4a41f71b7a512d6eb3b9c694" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 00b0c91f06209d9e4a41f71b7a512d6eb3b9c694 - base_revision: 00b0c91f06209d9e4a41f71b7a512d6eb3b9c694 - - platform: android - create_revision: 00b0c91f06209d9e4a41f71b7a512d6eb3b9c694 - base_revision: 00b0c91f06209d9e4a41f71b7a512d6eb3b9c694 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e460be0..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "editor.formatOnSave": true, - "editor.defaultFormatter": "Dart-Code.flutter", - "dart.lineLength": 120, - "[dart]": { - "editor.rulers": [ - 120 - ], - }, - "cSpell.words": [ - "gstatic", - "Linkding", - "linkdy", - "Linkdy" - ], - "cSpell.language": "en,es,tr", -} \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index c6e6507..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2024 JGeek00 - - Licensed 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. diff --git a/Marks.xcodeproj/project.pbxproj b/Marks.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b18a6dc --- /dev/null +++ b/Marks.xcodeproj/project.pbxproj @@ -0,0 +1,514 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 14E1B3CE58D36BFF1A2199C1 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22E006A11D594BFC00A9C4B4 /* OnboardingView.swift */; }; + 15077853ECD40C9B289FB608 /* LinkdingAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CCBB391B1E0E1E4EBE0EFC7 /* LinkdingAPI.swift */; }; + 41F00F4E7FFC1C0ACF71E398 /* MarksApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92575C7C710347F226EC74A /* MarksApp.swift */; }; + 457FCE503CCA82C5F27C6C90 /* Bookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CA428181B35885F7D9F4D55 /* Bookmark.swift */; }; + 5D86F3F0F603B248776916C7 /* BookmarksViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBFB5EFC9764B22A2622EA4A /* BookmarksViewModel.swift */; }; + 6BF0E1F0F4DEAF87B0B8DCF6 /* CollectionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE19F7619214271A8C12EEEB /* CollectionsView.swift */; }; + 76223AA04DF97B24C1490B20 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADEAC824576633CC77370262 /* ShareViewController.swift */; }; + 849C9CB4E1E8A6ABA1BC7251 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C29CB878BC334639E6194E2 /* SettingsView.swift */; }; + 8BDB7DAA6A2711B9499F5582 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 57D20912C19182A45914069B /* Assets.xcassets */; }; + 927BAD5AD47217E3F396CDA7 /* TagsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B13B9F2D890C7953531AC0D2 /* TagsView.swift */; }; + 96698499C0501D0A897D7E08 /* BookmarkRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C6ABE160A2C90EB965D811 /* BookmarkRow.swift */; }; + 969568D9996EB65550DAA24A /* ServerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07C21567B95F5069BA946252 /* ServerConfig.swift */; }; + A8B8D58C5B68F54DC20126C1 /* BookmarksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBE3C5E420F078D499B2D926 /* BookmarksView.swift */; }; + AE2EA9C6B9016C9986ADC8EE /* AddBookmarkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB2D194AD325ECE80A04979E /* AddBookmarkView.swift */; }; + B08F151637384EA9E054AC5F /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 938672D3D6ADC73B354B5EA5 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + BD2EAD8200FB69B95972146F /* ClaudeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69D868AF1DAF3F1BBEACBFF6 /* ClaudeService.swift */; }; + EE540B8367519EDE679C1B70 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCC3BB2525F0F63445D419B9 /* SearchView.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + BD17B6B2972DB25FA605D8AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0CC2596AE7F05EAF051B2FCD /* Project object */; + proxyType = 1; + remoteGlobalIDString = CF31B2655F8F30CF6DF3C26F; + remoteInfo = ShareExtension; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 93C7F00CFA9EABABB6323F6D /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + B08F151637384EA9E054AC5F /* ShareExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 03D800669E343FF305468424 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = ""; }; + 07C21567B95F5069BA946252 /* ServerConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfig.swift; sourceTree = ""; }; + 0D2CC53B01DF0FE51ADE5FCB /* Marks.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Marks.entitlements; sourceTree = ""; }; + 22E006A11D594BFC00A9C4B4 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = ""; }; + 57D20912C19182A45914069B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 5C29CB878BC334639E6194E2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + 5CCBB391B1E0E1E4EBE0EFC7 /* LinkdingAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkdingAPI.swift; sourceTree = ""; }; + 69D868AF1DAF3F1BBEACBFF6 /* ClaudeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClaudeService.swift; sourceTree = ""; }; + 86B2DE40098D2B39FFE1AC36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 8CA428181B35885F7D9F4D55 /* Bookmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bookmark.swift; sourceTree = ""; }; + 938672D3D6ADC73B354B5EA5 /* ShareExtension.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + AB2D194AD325ECE80A04979E /* AddBookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddBookmarkView.swift; sourceTree = ""; }; + AB6C53AB14A38FCD4CC7628D /* Marks.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Marks.app; sourceTree = BUILT_PRODUCTS_DIR; }; + ADEAC824576633CC77370262 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; + B0C6ABE160A2C90EB965D811 /* BookmarkRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkRow.swift; sourceTree = ""; }; + B13B9F2D890C7953531AC0D2 /* TagsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagsView.swift; sourceTree = ""; }; + BCC3BB2525F0F63445D419B9 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; + CBE3C5E420F078D499B2D926 /* BookmarksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksView.swift; sourceTree = ""; }; + CBFB5EFC9764B22A2622EA4A /* BookmarksViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksViewModel.swift; sourceTree = ""; }; + D92575C7C710347F226EC74A /* MarksApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarksApp.swift; sourceTree = ""; }; + E895C34E4D2A1C4709B25FF1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + FE19F7619214271A8C12EEEB /* CollectionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionsView.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXGroup section */ + 3952A081972B444674BEB51B /* Marks */ = { + isa = PBXGroup; + children = ( + 57D20912C19182A45914069B /* Assets.xcassets */, + 86B2DE40098D2B39FFE1AC36 /* Info.plist */, + 0D2CC53B01DF0FE51ADE5FCB /* Marks.entitlements */, + D92575C7C710347F226EC74A /* MarksApp.swift */, + 3EF3094F53F0378D1BF18508 /* Models */, + 7ABBFDF43A1EB773E0A49CFE /* Services */, + AF9CABF75E77168EF1D60F29 /* Views */, + ); + path = Marks; + sourceTree = ""; + }; + 3EF3094F53F0378D1BF18508 /* Models */ = { + isa = PBXGroup; + children = ( + 8CA428181B35885F7D9F4D55 /* Bookmark.swift */, + 07C21567B95F5069BA946252 /* ServerConfig.swift */, + ); + path = Models; + sourceTree = ""; + }; + 7A85D09B4E109E1D9CD8F5BB /* ShareExtension */ = { + isa = PBXGroup; + children = ( + E895C34E4D2A1C4709B25FF1 /* Info.plist */, + 03D800669E343FF305468424 /* ShareExtension.entitlements */, + ADEAC824576633CC77370262 /* ShareViewController.swift */, + ); + path = ShareExtension; + sourceTree = ""; + }; + 7ABBFDF43A1EB773E0A49CFE /* Services */ = { + isa = PBXGroup; + children = ( + 69D868AF1DAF3F1BBEACBFF6 /* ClaudeService.swift */, + 5CCBB391B1E0E1E4EBE0EFC7 /* LinkdingAPI.swift */, + ); + path = Services; + sourceTree = ""; + }; + AF9CABF75E77168EF1D60F29 /* Views */ = { + isa = PBXGroup; + children = ( + AB2D194AD325ECE80A04979E /* AddBookmarkView.swift */, + B0C6ABE160A2C90EB965D811 /* BookmarkRow.swift */, + CBE3C5E420F078D499B2D926 /* BookmarksView.swift */, + CBFB5EFC9764B22A2622EA4A /* BookmarksViewModel.swift */, + FE19F7619214271A8C12EEEB /* CollectionsView.swift */, + 22E006A11D594BFC00A9C4B4 /* OnboardingView.swift */, + BCC3BB2525F0F63445D419B9 /* SearchView.swift */, + 5C29CB878BC334639E6194E2 /* SettingsView.swift */, + B13B9F2D890C7953531AC0D2 /* TagsView.swift */, + ); + path = Views; + sourceTree = ""; + }; + BC60767DD65812CCBD41C38F = { + isa = PBXGroup; + children = ( + 3952A081972B444674BEB51B /* Marks */, + 7A85D09B4E109E1D9CD8F5BB /* ShareExtension */, + C6978BB2E0A71E9A349D5EB6 /* Products */, + ); + sourceTree = ""; + }; + C6978BB2E0A71E9A349D5EB6 /* Products */ = { + isa = PBXGroup; + children = ( + AB6C53AB14A38FCD4CC7628D /* Marks.app */, + 938672D3D6ADC73B354B5EA5 /* ShareExtension.appex */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 76C272776D8EBCCD3FB6715A /* Marks */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00981D0FC690B5F5F4CA68B9 /* Build configuration list for PBXNativeTarget "Marks" */; + buildPhases = ( + 81AF93AC59791A6311B9055B /* Sources */, + D56AC7DEA48961F856A6CEF6 /* Resources */, + 93C7F00CFA9EABABB6323F6D /* Embed Foundation Extensions */, + ); + buildRules = ( + ); + dependencies = ( + A87C510E52F149E7E3CA0283 /* PBXTargetDependency */, + ); + name = Marks; + packageProductDependencies = ( + ); + productName = Marks; + productReference = AB6C53AB14A38FCD4CC7628D /* Marks.app */; + productType = "com.apple.product-type.application"; + }; + CF31B2655F8F30CF6DF3C26F /* ShareExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 94AD43D2CB52900BE36CD8DA /* Build configuration list for PBXNativeTarget "ShareExtension" */; + buildPhases = ( + 2210C849B430CC6609106C62 /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ShareExtension; + packageProductDependencies = ( + ); + productName = ShareExtension; + productReference = 938672D3D6ADC73B354B5EA5 /* ShareExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0CC2596AE7F05EAF051B2FCD /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1630; + TargetAttributes = { + 76C272776D8EBCCD3FB6715A = { + DevelopmentTeam = AE5DZKJHGN; + ProvisioningStyle = Automatic; + }; + CF31B2655F8F30CF6DF3C26F = { + DevelopmentTeam = AE5DZKJHGN; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 4BACCD33EEE63890F06D7057 /* Build configuration list for PBXProject "Marks" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = BC60767DD65812CCBD41C38F; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 76C272776D8EBCCD3FB6715A /* Marks */, + CF31B2655F8F30CF6DF3C26F /* ShareExtension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D56AC7DEA48961F856A6CEF6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8BDB7DAA6A2711B9499F5582 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2210C849B430CC6609106C62 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 76223AA04DF97B24C1490B20 /* ShareViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 81AF93AC59791A6311B9055B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AE2EA9C6B9016C9986ADC8EE /* AddBookmarkView.swift in Sources */, + 457FCE503CCA82C5F27C6C90 /* Bookmark.swift in Sources */, + 96698499C0501D0A897D7E08 /* BookmarkRow.swift in Sources */, + A8B8D58C5B68F54DC20126C1 /* BookmarksView.swift in Sources */, + 5D86F3F0F603B248776916C7 /* BookmarksViewModel.swift in Sources */, + BD2EAD8200FB69B95972146F /* ClaudeService.swift in Sources */, + 6BF0E1F0F4DEAF87B0B8DCF6 /* CollectionsView.swift in Sources */, + 15077853ECD40C9B289FB608 /* LinkdingAPI.swift in Sources */, + 41F00F4E7FFC1C0ACF71E398 /* MarksApp.swift in Sources */, + 14E1B3CE58D36BFF1A2199C1 /* OnboardingView.swift in Sources */, + EE540B8367519EDE679C1B70 /* SearchView.swift in Sources */, + 969568D9996EB65550DAA24A /* ServerConfig.swift in Sources */, + 849C9CB4E1E8A6ABA1BC7251 /* SettingsView.swift in Sources */, + 927BAD5AD47217E3F396CDA7 /* TagsView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + A87C510E52F149E7E3CA0283 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CF31B2655F8F30CF6DF3C26F /* ShareExtension */; + targetProxy = BD17B6B2972DB25FA605D8AA /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 12B4EAB4496B20EF8B695599 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = AE5DZKJHGN; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_PREVIEWS = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 6.0; + }; + name = Release; + }; + 21D2ADFC1A27251BB64A773D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Marks/Marks.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Marks/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.magicive.marks; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 46C5C95D9B4F4A1E8ABD1A98 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Marks/Marks.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Marks/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.magicive.marks; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 5F64C301FBBC85007BB1F0C2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; + INFOPLIST_FILE = ShareExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.magicive.marks.ShareExtension; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 7AD80830605CAD3492E03039 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; + INFOPLIST_FILE = ShareExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.magicive.marks.ShareExtension; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B87C74506F7AEF79B42CC172 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = AE5DZKJHGN; + ENABLE_PREVIEWS = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 6.0; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00981D0FC690B5F5F4CA68B9 /* Build configuration list for PBXNativeTarget "Marks" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 21D2ADFC1A27251BB64A773D /* Debug */, + 46C5C95D9B4F4A1E8ABD1A98 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 4BACCD33EEE63890F06D7057 /* Build configuration list for PBXProject "Marks" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B87C74506F7AEF79B42CC172 /* Debug */, + 12B4EAB4496B20EF8B695599 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 94AD43D2CB52900BE36CD8DA /* Build configuration list for PBXNativeTarget "ShareExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7AD80830605CAD3492E03039 /* Debug */, + 5F64C301FBBC85007BB1F0C2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0CC2596AE7F05EAF051B2FCD /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Marks.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Marks.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/Marks.xcodeproj/xcshareddata/xcschemes/Marks.xcscheme similarity index 57% rename from ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to Marks.xcodeproj/xcshareddata/xcschemes/Marks.xcscheme index e3773d4..7ebd312 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/Marks.xcodeproj/xcshareddata/xcschemes/Marks.xcscheme @@ -1,10 +1,11 @@ + LastUpgradeVersion = "1630" + version = "1.7"> + buildImplicitDependencies = "YES" + runPostActionsOnFailure = "NO"> + BlueprintIdentifier = "76C272776D8EBCCD3FB6715A" + BuildableName = "Marks.app" + BlueprintName = "Marks" + ReferencedContainer = "container:Marks.xcodeproj"> + + + + @@ -26,56 +41,47 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + onlyGenerateCoverageForSpecifiedTargets = "NO"> + BlueprintIdentifier = "76C272776D8EBCCD3FB6715A" + BuildableName = "Marks.app" + BlueprintName = "Marks" + ReferencedContainer = "container:Marks.xcodeproj"> - - - - + + + BlueprintIdentifier = "76C272776D8EBCCD3FB6715A" + BuildableName = "Marks.app" + BlueprintName = "Marks" + ReferencedContainer = "container:Marks.xcodeproj"> + + + BlueprintIdentifier = "76C272776D8EBCCD3FB6715A" + BuildableName = "Marks.app" + BlueprintName = "Marks" + ReferencedContainer = "container:Marks.xcodeproj"> + + diff --git a/Marks/Assets.xcassets/AppIcon.appiconset/AppIcon.png b/Marks/Assets.xcassets/AppIcon.appiconset/AppIcon.png new file mode 100644 index 0000000..1332dcb Binary files /dev/null and b/Marks/Assets.xcassets/AppIcon.appiconset/AppIcon.png differ diff --git a/Marks/Assets.xcassets/AppIcon.appiconset/Contents.json b/Marks/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..cefcc87 --- /dev/null +++ b/Marks/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "AppIcon.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Marks/Assets.xcassets/Contents.json b/Marks/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Marks/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Marks/Info.plist b/Marks/Info.plist new file mode 100644 index 0000000..f92ba43 --- /dev/null +++ b/Marks/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDisplayName + Marks + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + diff --git a/ios/Share Extension/Share Extension.entitlements b/Marks/Marks.entitlements similarity index 70% rename from ios/Share Extension/Share Extension.entitlements rename to Marks/Marks.entitlements index b9766cf..02a7360 100644 --- a/ios/Share Extension/Share Extension.entitlements +++ b/Marks/Marks.entitlements @@ -2,11 +2,9 @@ - com.apple.developer.networking.wifi-info - com.apple.security.application-groups - group.com.jgeek00.linkdy + group.com.magicive.marks diff --git a/Marks/MarksApp.swift b/Marks/MarksApp.swift new file mode 100644 index 0000000..04b3777 --- /dev/null +++ b/Marks/MarksApp.swift @@ -0,0 +1,52 @@ +import SwiftUI + +@main +struct MarksApp: App { + @State private var serverConfig: ServerConfig? = ServerConfig.load() + + var body: some Scene { + WindowGroup { + if let config = serverConfig { + MainContainer(config: config) { + config.delete() + serverConfig = nil + } + } else { + OnboardingView { newConfig in + newConfig.save() + serverConfig = newConfig + } + } + } + } +} + +// Holds the API + ViewModel so they survive re-renders +struct MainContainer: View { + let config: ServerConfig + let onDisconnect: () -> Void + + @State private var viewModel: BookmarksViewModel + + init(config: ServerConfig, onDisconnect: @escaping () -> Void) { + self.config = config + self.onDisconnect = onDisconnect + let api = LinkdingAPI(config: config) + let claude = ClaudeService.load() + _viewModel = State(wrappedValue: BookmarksViewModel(api: api, claude: claude)) + } + + var body: some View { + TabView { + Tab("Bookmarks", systemImage: "bookmark") { + BookmarksView(viewModel: viewModel, onDisconnect: onDisconnect) + } + Tab("Tags", systemImage: "tag") { + TagsView(viewModel: viewModel) + } + Tab(role: .search) { + SearchView(viewModel: viewModel) + } + } + } +} diff --git a/Marks/Models/Bookmark.swift b/Marks/Models/Bookmark.swift new file mode 100644 index 0000000..fdd8295 --- /dev/null +++ b/Marks/Models/Bookmark.swift @@ -0,0 +1,73 @@ +import Foundation + +struct Bookmark: Codable, Identifiable, Sendable, Hashable { + let id: Int + var url: String + var title: String + var description: String + var tagNames: [String] + var dateAdded: Date + var dateModified: Date + var isArchived: Bool + var unread: Bool + var shared: Bool + var websiteTitle: String? + var websiteDescription: String? + var faviconUrl: String? + var previewImageUrl: String? + + // AI-enriched fields stored locally + var aiSummary: String? + var aiTags: [String]? + + enum CodingKeys: String, CodingKey { + case id, url, title, description, unread, shared + case tagNames = "tag_names" + case dateAdded = "date_added" + case dateModified = "date_modified" + case isArchived = "is_archived" + case websiteTitle = "website_title" + case websiteDescription = "website_description" + case faviconUrl = "favicon_url" + case previewImageUrl = "preview_image_url" + } + + var displayTitle: String { + if !title.isEmpty { return title } + if let t = websiteTitle, !t.isEmpty { return t } + return url + } + + var domain: String { + URL(string: url)?.host ?? url + } +} + +struct BookmarkResponse: Codable, Sendable { + let count: Int + let next: String? + let previous: String? + let results: [Bookmark] +} + +struct BookmarkCreate: Codable, Sendable { + let url: String + let title: String + let tagNames: [String] + let isArchived: Bool + let unread: Bool + let shared: Bool + + enum CodingKeys: String, CodingKey { + case url, title, unread, shared + case tagNames = "tag_names" + case isArchived = "is_archived" + } +} + +struct SmartCollection: Identifiable, Sendable { + let id = UUID() + let name: String + let description: String + let bookmarkIds: [Int] +} diff --git a/Marks/Models/ServerConfig.swift b/Marks/Models/ServerConfig.swift new file mode 100644 index 0000000..f83d40d --- /dev/null +++ b/Marks/Models/ServerConfig.swift @@ -0,0 +1,38 @@ +import Foundation + +struct ServerConfig: Codable, Sendable { + var host: String + var port: Int? + var path: String + var token: String + var useHttps: Bool + + var baseUrl: String { + var url = useHttps ? "https://" : "http://" + url += host + if let port { url += ":\(port)" } + if !path.isEmpty { url += path } + return url + } +} + +extension ServerConfig { + private static let key = "serverConfig" + private static let appGroupId = "group.com.magicive.marks" + + static func load() -> ServerConfig? { + guard let data = UserDefaults.standard.data(forKey: key) else { return nil } + return try? JSONDecoder().decode(ServerConfig.self, from: data) + } + + func save() { + guard let data = try? JSONEncoder().encode(self) else { return } + UserDefaults.standard.set(data, forKey: ServerConfig.key) + UserDefaults(suiteName: ServerConfig.appGroupId)?.set(data, forKey: ServerConfig.key) + } + + func delete() { + UserDefaults.standard.removeObject(forKey: ServerConfig.key) + UserDefaults(suiteName: ServerConfig.appGroupId)?.removeObject(forKey: ServerConfig.key) + } +} diff --git a/Marks/Services/ClaudeService.swift b/Marks/Services/ClaudeService.swift new file mode 100644 index 0000000..deb20ab --- /dev/null +++ b/Marks/Services/ClaudeService.swift @@ -0,0 +1,147 @@ +import Foundation + +struct ClaudeService: Sendable { + let apiKey: String + static let defaultsKey = "openRouterApiKey" + // Cheap, fast model — change to any OpenRouter model slug + private static let model = "google/gemini-2.0-flash-lite-001" + + static func load() -> ClaudeService? { + guard let key = UserDefaults.standard.string(forKey: defaultsKey), !key.isEmpty else { return nil } + return ClaudeService(apiKey: key) + } + + static func save(apiKey: String) { + UserDefaults.standard.set(apiKey, forKey: defaultsKey) + } + + func enrich(bookmark: Bookmark) async throws -> (summary: String, tags: [String]) { + let prompt = """ + Analyze this bookmark: + URL: \(bookmark.url) + Title: \(bookmark.displayTitle) + Existing tags: \(bookmark.tagNames.joined(separator: ", ")) + + Respond with ONLY valid JSON, no markdown: + {"summary": "One or two sentence summary of what this page is about.", "tags": ["tag1", "tag2", "tag3"]} + + Rules: summary under 120 chars, 3-5 tags, lowercase, no # symbol, no existing tags duplicated. + """ + let text = try await callModel(prompt: prompt, maxTokens: 256) + return parseEnrichResponse(text) + } + + func semanticSearch(query: String, in bookmarks: [Bookmark]) async throws -> [Bookmark] { + guard !bookmarks.isEmpty else { return [] } + let list = bookmarks.enumerated().map { i, b in + "[\(i)] \(b.displayTitle) — \(b.domain)\(b.aiSummary.map { " — \($0)" } ?? "")" + }.joined(separator: "\n") + let prompt = """ + Search query: "\(query)" + + Find relevant bookmarks from the list. Return ONLY a JSON array of indices in relevance order. Example: [3, 0, 7] + Return [] if nothing matches. + + Bookmarks: + \(list) + """ + let text = try await callModel(prompt: prompt, maxTokens: 256) + let indices = parseIntArray(text) + return indices.compactMap { i in i < bookmarks.count ? bookmarks[i] : nil } + } + + func generateCollections(from bookmarks: [Bookmark]) async throws -> [SmartCollection] { + guard !bookmarks.isEmpty else { return [] } + let list = bookmarks.prefix(150).enumerated().map { i, b in + "[\(i)] \(b.displayTitle) [\(b.tagNames.joined(separator: ","))]" + }.joined(separator: "\n") + let prompt = """ + Group these bookmarks into 3-6 meaningful themed collections. + Respond with ONLY valid JSON, no markdown: + [{"name": "Collection Name", "description": "Brief description", "indices": [0, 1, 2]}] + + Bookmarks: + \(list) + """ + let text = try await callModel(prompt: prompt, maxTokens: 1024) + return parseCollections(text, bookmarks: Array(bookmarks.prefix(150))) + } + + private func callModel(prompt: String, maxTokens: Int) async throws -> String { + let url = URL(string: "https://openrouter.ai/api/v1/chat/completions")! + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("https://marks.app", forHTTPHeaderField: "HTTP-Referer") + request.setValue("Marks", forHTTPHeaderField: "X-Title") + + let body: [String: Any] = [ + "model": Self.model, + "max_tokens": maxTokens, + "messages": [["role": "user", "content": prompt]] + ] + request.httpBody = try JSONSerialization.data(withJSONObject: body) + + print("[AI] callModel: POST openrouter model=\(Self.model) maxTokens=\(maxTokens)") + let (data, response) = try await URLSession.shared.data(for: request) + let status = (response as? HTTPURLResponse)?.statusCode ?? 0 + print("[AI] callModel: status=\(status) bytes=\(data.count)") + guard status == 200 else { + let body = String(data: data, encoding: .utf8) ?? "" + print("[AI] callModel: error body=\(body.prefix(200))") + throw APIError.badStatus(status) + } + + struct Choice: Codable { + struct Message: Codable { let content: String } + let message: Message + } + struct Response: Codable { let choices: [Choice] } + let content = (try JSONDecoder().decode(Response.self, from: data)).choices.first?.message.content ?? "" + print("[AI] callModel: response=\(content.prefix(100))") + return content + } + + private func parseEnrichResponse(_ text: String) -> (summary: String, tags: [String]) { + let cleaned = extractJSON(from: text) + guard let data = cleaned.data(using: .utf8), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let summary = json["summary"] as? String, + let tags = json["tags"] as? [String] else { return (text, []) } + return (summary, tags) + } + + private func parseIntArray(_ text: String) -> [Int] { + let cleaned = extractJSON(from: text) + guard let data = cleaned.data(using: .utf8), + let arr = try? JSONSerialization.jsonObject(with: data) as? [Int] else { return [] } + return arr + } + + private func parseCollections(_ text: String, bookmarks: [Bookmark]) -> [SmartCollection] { + let cleaned = extractJSON(from: text) + guard let data = cleaned.data(using: .utf8), + let arr = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] else { return [] } + return arr.compactMap { dict in + guard let name = dict["name"] as? String, + let indices = dict["indices"] as? [Int] else { return nil } + let desc = dict["description"] as? String ?? "" + let ids = indices.compactMap { i -> Int? in i < bookmarks.count ? bookmarks[i].id : nil } + return SmartCollection(name: name, description: desc, bookmarkIds: ids) + } + } + + private func extractJSON(from text: String) -> String { + if let start = text.range(of: "```json\n"), let end = text.range(of: "\n```") { + return String(text[start.upperBound.. URL { + var components = URLComponents() + components.scheme = config.useHttps ? "https" : "http" + components.host = config.host + components.port = config.port + components.path = config.path.isEmpty ? path : config.path + path + if !queryItems.isEmpty { components.queryItems = queryItems } + guard let url = components.url else { throw APIError.invalidUrl } + return url + } + + private func authorizedRequest(url: URL, method: String = "GET", body: Data? = nil) -> URLRequest { + var req = URLRequest(url: url) + req.httpMethod = method + req.setValue("Token \(config.token)", forHTTPHeaderField: "Authorization") + if let body { + req.setValue("application/json", forHTTPHeaderField: "Content-Type") + req.httpBody = body + } + return req + } + + func fetchBookmarks(search: String = "", offset: Int = 0, limit: Int = 50) async throws -> BookmarkResponse { + var items: [URLQueryItem] = [ + .init(name: "limit", value: "\(limit)"), + .init(name: "offset", value: "\(offset)") + ] + if !search.isEmpty { items.append(.init(name: "q", value: search)) } + let url = try makeUrl(path: "/api/bookmarks/", queryItems: items) + let (data, response) = try await session.data(for: authorizedRequest(url: url)) + guard (response as? HTTPURLResponse)?.statusCode == 200 else { + throw APIError.badStatus((response as? HTTPURLResponse)?.statusCode ?? 0) + } + return try decoder.decode(BookmarkResponse.self, from: data) + } + + func fetchBookmarksFromUrl(_ urlString: String) async throws -> BookmarkResponse { + guard let url = URL(string: urlString) else { throw APIError.invalidUrl } + let (data, _) = try await session.data(for: authorizedRequest(url: url)) + return try decoder.decode(BookmarkResponse.self, from: data) + } + + func createBookmark(_ create: BookmarkCreate) async throws -> Bookmark { + let body = try JSONEncoder().encode(create) + let url = try makeUrl(path: "/api/bookmarks/") + let (data, response) = try await session.data(for: authorizedRequest(url: url, method: "POST", body: body)) + guard (response as? HTTPURLResponse)?.statusCode == 201 else { + throw APIError.badStatus((response as? HTTPURLResponse)?.statusCode ?? 0) + } + return try decoder.decode(Bookmark.self, from: data) + } + + func updateBookmark(id: Int, tagNames: [String]) async throws -> Bookmark { + let body = try JSONEncoder().encode(["tag_names": tagNames]) + let url = try makeUrl(path: "/api/bookmarks/\(id)/") + let (data, response) = try await session.data(for: authorizedRequest(url: url, method: "PATCH", body: body)) + guard (response as? HTTPURLResponse)?.statusCode == 200 else { + throw APIError.badStatus((response as? HTTPURLResponse)?.statusCode ?? 0) + } + return try decoder.decode(Bookmark.self, from: data) + } + + func deleteBookmark(id: Int) async throws { + let url = try makeUrl(path: "/api/bookmarks/\(id)/") + let (_, response) = try await session.data(for: authorizedRequest(url: url, method: "DELETE")) + guard (response as? HTTPURLResponse)?.statusCode == 204 else { + throw APIError.badStatus((response as? HTTPURLResponse)?.statusCode ?? 0) + } + } + + func archiveBookmark(id: Int) async throws { + let url = try makeUrl(path: "/api/bookmarks/\(id)/archive/") + let (_, response) = try await session.data(for: authorizedRequest(url: url, method: "POST")) + guard let code = (response as? HTTPURLResponse)?.statusCode, code == 200 || code == 204 else { + throw APIError.badStatus((response as? HTTPURLResponse)?.statusCode ?? 0) + } + } + + func verifyConnection() async throws { + let url = try makeUrl(path: "/api/bookmarks/", queryItems: [.init(name: "limit", value: "1")]) + let (_, response) = try await session.data(for: authorizedRequest(url: url)) + guard (response as? HTTPURLResponse)?.statusCode == 200 else { + throw APIError.badStatus((response as? HTTPURLResponse)?.statusCode ?? 0) + } + } +} diff --git a/Marks/Views/AddBookmarkView.swift b/Marks/Views/AddBookmarkView.swift new file mode 100644 index 0000000..7d4cb97 --- /dev/null +++ b/Marks/Views/AddBookmarkView.swift @@ -0,0 +1,88 @@ +import SwiftUI + +struct AddBookmarkView: View { + @Bindable var viewModel: BookmarksViewModel + @Environment(\.dismiss) private var dismiss + + @State private var url = "" + @State private var title = "" + @State private var tagsText = "" + @State private var isSaving = false + @State private var error: String? + + var body: some View { + NavigationStack { + Form { + Section { + TextField("https://", text: $url) + .keyboardType(.URL) + .textInputAutocapitalization(.never) + .autocorrectionDisabled() + } header: { + Text("URL") + } + + Section { + TextField("Optional", text: $title) + } header: { + Text("Title") + } + + Section { + TextField("comma separated", text: $tagsText) + .textInputAutocapitalization(.never) + .autocorrectionDisabled() + } header: { + Text("Tags") + } footer: { + Text("Separate tags with commas") + } + + if let error { + Section { + Text(error) + .foregroundStyle(.red) + .font(.footnote) + } + } + } + .navigationTitle("Add Bookmark") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .cancellationAction) { + Button("Cancel") { dismiss() } + } + ToolbarItem(placement: .confirmationAction) { + Button("Save") { save() } + .disabled(url.trimmingCharacters(in: .whitespaces).isEmpty || isSaving) + .overlay { + if isSaving { ProgressView().scaleEffect(0.7) } + } + } + } + } + } + + private func save() { + var urlString = url.trimmingCharacters(in: .whitespaces) + if !urlString.hasPrefix("http://") && !urlString.hasPrefix("https://") { + urlString = "https://" + urlString + } + guard URL(string: urlString) != nil else { + error = "Invalid URL" + return + } + let tags = tagsText.split(separator: ",").map { $0.trimmingCharacters(in: .whitespaces) }.filter { !$0.isEmpty } + isSaving = true + error = nil + Task { + do { + try await viewModel.addBookmark(url: urlString, title: title.trimmingCharacters(in: .whitespaces), tags: tags) + dismiss() + } catch { + self.error = error.localizedDescription + isSaving = false + } + } + } +} diff --git a/Marks/Views/BookmarkRow.swift b/Marks/Views/BookmarkRow.swift new file mode 100644 index 0000000..2e7f999 --- /dev/null +++ b/Marks/Views/BookmarkRow.swift @@ -0,0 +1,93 @@ +import SwiftUI + +struct BookmarkRow: View { + let bookmark: Bookmark + + var body: some View { + VStack(alignment: .leading, spacing: 6) { + HStack(alignment: .top, spacing: 11) { + FaviconView(url: bookmark.faviconUrl) + .padding(.top, 1) + + VStack(alignment: .leading, spacing: 4) { + Text(bookmark.displayTitle) + .font(.system(size: 22, weight: .medium)) + .foregroundStyle(.primary) + .lineLimit(2) + .fixedSize(horizontal: false, vertical: true) + + Text(bookmark.domain) + .font(.system(size: 16)) + .foregroundStyle(.tertiary) + } + } + + if let summary = bookmark.aiSummary { + Text(summary) + .font(.system(size: 15)) + .foregroundStyle(.secondary) + .lineLimit(2) + .padding(.leading, 40) + } + + if !effectiveTags.isEmpty { + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 6) { + ForEach(effectiveTags, id: \.self) { tag in + Text(tag) + .font(.system(size: 12, weight: .medium)) + .foregroundStyle(.blue) + .padding(.horizontal, 9) + .padding(.vertical, 4) + .background(Color.blue.opacity(0.1)) + .clipShape(Capsule()) + } + } + } + .padding(.leading, 40) + } + } + .padding(.vertical, 14) + .contentShape(Rectangle()) + } + + private var effectiveTags: [String] { + let base = bookmark.tagNames + let ai = bookmark.aiTags ?? [] + let extra = ai.filter { !base.contains($0) }.prefix(3) + return (base + extra).prefix(6).map { $0 } + } +} + +struct FaviconView: View { + let url: String? + + var body: some View { + Group { + if let urlString = url, let faviconUrl = URL(string: urlString) { + AsyncImage(url: faviconUrl) { phase in + switch phase { + case .success(let image): + image.resizable().scaledToFit() + default: + placeholder + } + } + } else { + placeholder + } + } + .frame(width: 26, height: 26) + .clipShape(RoundedRectangle(cornerRadius: 5)) + } + + private var placeholder: some View { + RoundedRectangle(cornerRadius: 4) + .fill(Color(.systemGray5)) + .overlay { + Image(systemName: "bookmark") + .font(.system(size: 9, weight: .medium)) + .foregroundStyle(Color(.systemGray2)) + } + } +} diff --git a/Marks/Views/BookmarksView.swift b/Marks/Views/BookmarksView.swift new file mode 100644 index 0000000..96d1b83 --- /dev/null +++ b/Marks/Views/BookmarksView.swift @@ -0,0 +1,142 @@ +import SwiftUI + +struct BookmarksView: View { + @Bindable var viewModel: BookmarksViewModel + let onDisconnect: () -> Void + + @Environment(\.openURL) private var openURL + @State private var showSettings = false + @State private var showCollections = false + @State private var showAddBookmark = false + + var body: some View { + NavigationStack { + List { + ForEach(viewModel.bookmarks) { bookmark in + BookmarkRow(bookmark: bookmark) + .onTapGesture { + if let url = URL(string: bookmark.url) { openURL(url) } + } + .onAppear { maybeLoadMore(bookmark) } + .listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) + .listRowSeparator(.visible) + .swipeActions(edge: .trailing, allowsFullSwipe: true) { + Button(role: .destructive) { + Task { await viewModel.delete(bookmark) } + } label: { + Label("Delete", systemImage: "trash") + } + } + .swipeActions(edge: .leading) { + Button { + Task { await viewModel.archive(bookmark) } + } label: { + Label("Archive", systemImage: "archivebox") + } + .tint(.orange) + } + } + + if viewModel.isLoadingMore { + HStack { Spacer(); ProgressView(); Spacer() } + .listRowSeparator(.hidden) + } + } + .listStyle(.plain) + .navigationTitle("Bookmarks") + .navigationBarTitleDisplayMode(.large) + .toolbar { + ToolbarItem(placement: .topBarLeading) { + if viewModel.claude != nil { + Menu { + Button { + Task { await viewModel.generateSmartCollections() } + showCollections = true + } label: { + Label("Smart Collections", systemImage: "sparkles") + } + Button { + Task { await viewModel.enrichAll() } + } label: { + Label("Enrich All with AI", systemImage: "wand.and.stars") + } + } label: { + Image(systemName: "sparkles") + } + } + } + ToolbarItem(placement: .topBarTrailing) { + HStack(spacing: 16) { + Button { showAddBookmark = true } label: { + Image(systemName: "plus") + } + Button { showSettings = true } label: { + Image(systemName: "gearshape") + } + } + } + } + .overlay { + if viewModel.isLoading && viewModel.bookmarks.isEmpty { + ProgressView() + } + if !viewModel.isLoading && viewModel.bookmarks.isEmpty { + ContentUnavailableView("No Bookmarks", systemImage: "bookmark", description: Text("Bookmarks you save will appear here.")) + } + } + .overlay(alignment: .bottom) { + if viewModel.enrichmentProgress > 0 { + enrichmentBanner + } + } + } + .sheet(isPresented: $showSettings) { + SettingsView(viewModel: viewModel, onDisconnect: onDisconnect) + } + .sheet(isPresented: $showCollections) { + CollectionsView(viewModel: viewModel) + } + .sheet(isPresented: $showAddBookmark) { + AddBookmarkView(viewModel: viewModel) + } + .refreshable { + await viewModel.load() + } + .task { + if viewModel.bookmarks.isEmpty { + await viewModel.load() + } + } + .alert("Error", isPresented: Binding( + get: { viewModel.error != nil }, + set: { if !$0 { viewModel.error = nil } } + )) { + Button("OK") { viewModel.error = nil } + } message: { + Text(viewModel.error ?? "") + } + } + + private var enrichmentBanner: some View { + HStack(spacing: 10) { + ProgressView(value: viewModel.enrichmentProgress) + .progressViewStyle(.linear) + .tint(.primary) + Text("Adding AI summaries…") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + } + .padding(.horizontal, 20) + .padding(.vertical, 12) + .background(.regularMaterial) + .clipShape(RoundedRectangle(cornerRadius: 12)) + .padding(.horizontal, 16) + .padding(.bottom, 8) + } + + private func maybeLoadMore(_ bookmark: Bookmark) { + guard let last = viewModel.bookmarks.last, last.id == bookmark.id, + viewModel.nextPageUrl != nil, !viewModel.isLoadingMore else { return } + Task { await viewModel.loadMore() } + } +} diff --git a/Marks/Views/BookmarksViewModel.swift b/Marks/Views/BookmarksViewModel.swift new file mode 100644 index 0000000..4803c63 --- /dev/null +++ b/Marks/Views/BookmarksViewModel.swift @@ -0,0 +1,220 @@ +import Foundation +import Observation + +@Observable +@MainActor +final class BookmarksViewModel { + var bookmarks: [Bookmark] = [] + var isLoading = false + var isLoadingMore = false + var error: String? + var searchQuery = "" + var nextPageUrl: String? + var smartCollections: [SmartCollection] = [] + var isGeneratingCollections = false + var enrichmentProgress: Double = 0 + + private let api: LinkdingAPI + private(set) var claude: ClaudeService? + private var enrichTask: Task? + + init(api: LinkdingAPI, claude: ClaudeService?) { + self.api = api + self.claude = claude + } + + func updateClaude(_ service: ClaudeService?) { + claude = service + } + + func load() async { + isLoading = true + error = nil + do { + let response = try await api.fetchBookmarks(search: searchQuery) + bookmarks = response.results + nextPageUrl = response.next + restoreAIData() + } catch { + self.error = error.localizedDescription + } + isLoading = false + startEnrichment() + } + + func loadMore() async { + guard let next = nextPageUrl, !isLoadingMore else { return } + isLoadingMore = true + do { + let response = try await api.fetchBookmarksFromUrl(next) + bookmarks.append(contentsOf: response.results) + nextPageUrl = response.next + restoreAIData() + } catch { + self.error = error.localizedDescription + } + isLoadingMore = false + } + + func search() async { + isLoading = true + do { + let response = try await api.fetchBookmarks(search: searchQuery) + bookmarks = response.results + nextPageUrl = response.next + restoreAIData() + } catch { + self.error = error.localizedDescription + } + isLoading = false + } + + func semanticSearch() async { + guard let claude, !searchQuery.isEmpty else { return } + isLoading = true + do { + // Search over all loaded bookmarks semantically + let allResponse = try await api.fetchBookmarks(limit: 200) + var all = allResponse.results + // Restore AI data so summaries are available for ranking + restoreAIData(into: &all) + bookmarks = try await claude.semanticSearch(query: searchQuery, in: all) + nextPageUrl = nil + } catch { + self.error = error.localizedDescription + } + isLoading = false + } + + func addBookmark(url: String, title: String, tags: [String]) async throws { + let create = BookmarkCreate(url: url, title: title, tagNames: tags, isArchived: false, unread: false, shared: false) + let bookmark = try await api.createBookmark(create) + bookmarks.insert(bookmark, at: 0) + print("[AI] addBookmark: saved id=\(bookmark.id) claude=\(claude != nil ? "present" : "nil")") + guard let claude else { return } + Task { + print("[AI] addBookmark: starting enrich for id=\(bookmark.id) url=\(bookmark.url)") + do { + let (summary, aiTags) = try await claude.enrich(bookmark: bookmark) + print("[AI] addBookmark: enrich success summary=\(summary.prefix(60)) tags=\(aiTags)") + guard let i = bookmarks.firstIndex(where: { $0.id == bookmark.id }) else { + print("[AI] addBookmark: bookmark id=\(bookmark.id) not found in list after enrich") + return + } + bookmarks[i].aiSummary = summary + bookmarks[i].aiTags = aiTags + saveAIData(for: bookmarks[i]) + } catch { + print("[AI] addBookmark: enrich FAILED \(error)") + self.error = "AI enrichment failed: \(error.localizedDescription)" + } + } + } + + func delete(_ bookmark: Bookmark) async { + do { + try await api.deleteBookmark(id: bookmark.id) + bookmarks.removeAll { $0.id == bookmark.id } + } catch { + self.error = error.localizedDescription + } + } + + func archive(_ bookmark: Bookmark) async { + do { + try await api.archiveBookmark(id: bookmark.id) + bookmarks.removeAll { $0.id == bookmark.id } + } catch { + self.error = error.localizedDescription + } + } + + func generateSmartCollections() async { + guard let claude, !bookmarks.isEmpty else { return } + isGeneratingCollections = true + do { + let allResponse = try await api.fetchBookmarks(limit: 200) + smartCollections = try await claude.generateCollections(from: allResponse.results) + } catch { + self.error = error.localizedDescription + } + isGeneratingCollections = false + } + + func enrichAll() async { + guard let claude else { return } + let toEnrich = bookmarks.indices.filter { bookmarks[$0].aiSummary == nil } + guard !toEnrich.isEmpty else { return } + enrichmentProgress = 0 + for (done, i) in toEnrich.enumerated() { + do { + let (summary, tags) = try await claude.enrich(bookmark: bookmarks[i]) + bookmarks[i].aiSummary = summary + bookmarks[i].aiTags = tags + saveAIData(for: bookmarks[i]) + enrichmentProgress = Double(done + 1) / Double(toEnrich.count) + } catch { + break + } + } + enrichmentProgress = 0 + } + + // Silently enrich new bookmarks that lack summaries (background, non-blocking) + private func startEnrichment() { + guard claude != nil else { + print("[AI] startEnrichment: skipped (no claude)") + return + } + enrichTask?.cancel() + enrichTask = Task { [weak self] in + guard let self else { return } + let indices = await MainActor.run { bookmarks.indices.filter { bookmarks[$0].aiSummary == nil }.prefix(5) } + print("[AI] startEnrichment: \(indices.count) bookmarks to enrich") + for i in indices { + guard !Task.isCancelled else { return } + guard let claude = await MainActor.run(body: { self.claude }) else { return } + do { + let bm = await MainActor.run { bookmarks[i] } + print("[AI] startEnrichment: enriching id=\(bm.id) \(bm.url)") + let (summary, tags) = try await claude.enrich(bookmark: bm) + print("[AI] startEnrichment: done id=\(bm.id) summary=\(summary.prefix(60))") + await MainActor.run { + guard i < bookmarks.count else { return } + bookmarks[i].aiSummary = summary + bookmarks[i].aiTags = tags + saveAIData(for: bookmarks[i]) + } + } catch { + print("[AI] startEnrichment: enrich FAILED id=\(i) \(error)") + break + } + } + } + } + + // MARK: AI persistence + + private func saveAIData(for bookmark: Bookmark) { + var store = UserDefaults.standard.dictionary(forKey: "aiData") as? [String: [String: Any]] ?? [:] + store["\(bookmark.id)"] = [ + "summary": bookmark.aiSummary ?? "", + "tags": bookmark.aiTags ?? [] + ] + UserDefaults.standard.set(store, forKey: "aiData") + } + + private func restoreAIData() { + restoreAIData(into: &bookmarks) + } + + private func restoreAIData(into list: inout [Bookmark]) { + let store = UserDefaults.standard.dictionary(forKey: "aiData") as? [String: [String: Any]] ?? [:] + for i in list.indices { + if let d = store["\(list[i].id)"] { + list[i].aiSummary = (d["summary"] as? String).flatMap { $0.isEmpty ? nil : $0 } + list[i].aiTags = d["tags"] as? [String] + } + } + } +} diff --git a/Marks/Views/CollectionsView.swift b/Marks/Views/CollectionsView.swift new file mode 100644 index 0000000..65ac644 --- /dev/null +++ b/Marks/Views/CollectionsView.swift @@ -0,0 +1,66 @@ +import SwiftUI + +struct CollectionsView: View { + @Bindable var viewModel: BookmarksViewModel + @Environment(\.dismiss) private var dismiss + + var body: some View { + NavigationStack { + Group { + if viewModel.isGeneratingCollections { + VStack(spacing: 16) { + ProgressView() + Text("Building smart collections…") + .font(.system(size: 15)) + .foregroundStyle(.secondary) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } else if viewModel.smartCollections.isEmpty { + ContentUnavailableView( + "No Collections Yet", + systemImage: "sparkles", + description: Text("Tap \"Smart Collections\" to group your bookmarks by topic.") + ) + } else { + List(viewModel.smartCollections) { collection in + Section { + let items = viewModel.bookmarks.filter { collection.bookmarkIds.contains($0.id) } + ForEach(items) { bookmark in + BookmarkRow(bookmark: bookmark) + .listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) + } + } header: { + VStack(alignment: .leading, spacing: 2) { + Text(collection.name) + .font(.system(size: 14, weight: .semibold)) + .foregroundStyle(.primary) + if !collection.description.isEmpty { + Text(collection.description) + .font(.system(size: 12)) + .foregroundStyle(.secondary) + } + } + .padding(.vertical, 4) + } + } + .listStyle(.insetGrouped) + } + } + .navigationTitle("Smart Collections") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .topBarLeading) { + Button { + Task { await viewModel.generateSmartCollections() } + } label: { + Image(systemName: "arrow.clockwise") + } + .disabled(viewModel.isGeneratingCollections) + } + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } + } + } + } +} diff --git a/Marks/Views/OnboardingView.swift b/Marks/Views/OnboardingView.swift new file mode 100644 index 0000000..2b19ff0 --- /dev/null +++ b/Marks/Views/OnboardingView.swift @@ -0,0 +1,144 @@ +import SwiftUI + +struct OnboardingView: View { + let onConnect: (ServerConfig) -> Void + + @State private var urlText = "" + @State private var token = "" + @State private var isConnecting = false + @State private var errorMessage: String? + @FocusState private var focused: Field? + + enum Field { case url, token } + + var body: some View { + VStack(spacing: 0) { + Spacer() + + VStack(alignment: .leading, spacing: 8) { + Text("Marks") + .font(.system(size: 42, weight: .semibold, design: .rounded)) + Text("Your bookmarks, beautifully.") + .font(.system(size: 17)) + .foregroundStyle(.secondary) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 28) + .padding(.bottom, 48) + + VStack(spacing: 14) { + VStack(alignment: .leading, spacing: 6) { + Text("Server URL") + .font(.system(size: 13, weight: .medium)) + .foregroundStyle(.secondary) + .padding(.horizontal, 2) + TextField("https://links.example.com", text: $urlText) + .textContentType(.URL) + .keyboardType(.URL) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + .focused($focused, equals: .url) + .submitLabel(.next) + .onSubmit { focused = .token } + .padding(14) + .background(Color(.systemGray6)) + .clipShape(RoundedRectangle(cornerRadius: 12)) + } + + VStack(alignment: .leading, spacing: 6) { + Text("API Token") + .font(.system(size: 13, weight: .medium)) + .foregroundStyle(.secondary) + .padding(.horizontal, 2) + SecureField("Paste your token", text: $token) + .textContentType(.password) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + .focused($focused, equals: .token) + .submitLabel(.done) + .onSubmit { Task { await connect() } } + .padding(14) + .background(Color(.systemGray6)) + .clipShape(RoundedRectangle(cornerRadius: 12)) + Text("Find your token at Settings → API Token in Linkding.") + .font(.system(size: 12)) + .foregroundStyle(.tertiary) + .padding(.horizontal, 2) + } + } + .padding(.horizontal, 24) + + if let err = errorMessage { + Text(err) + .font(.system(size: 14)) + .foregroundStyle(.red) + .padding(.top, 12) + .padding(.horizontal, 28) + } + + Button { + Task { await connect() } + } label: { + Group { + if isConnecting { + ProgressView().tint(.white) + } else { + Text("Connect") + .font(.system(size: 17, weight: .semibold)) + } + } + .frame(maxWidth: .infinity) + .frame(height: 52) + .background(canConnect ? Color.primary : Color(.systemGray4)) + .foregroundStyle(canConnect ? Color(UIColor.systemBackground) : Color(.systemGray2)) + .clipShape(RoundedRectangle(cornerRadius: 14)) + } + .disabled(!canConnect || isConnecting) + .padding(.horizontal, 24) + .padding(.top, 24) + + Spacer() + } + } + + private var canConnect: Bool { !urlText.isEmpty && !token.isEmpty } + + private func connect() async { + focused = nil + isConnecting = true + errorMessage = nil + + do { + let config = try parseConfig() + let api = LinkdingAPI(config: config) + try await api.verifyConnection() + onConnect(config) + } catch APIError.badStatus(401) { + errorMessage = "Invalid token. Check your API token in Linkding settings." + } catch APIError.badStatus(let code) { + errorMessage = "Server returned \(code). Check the URL." + } catch { + errorMessage = "Could not connect. Check the URL and try again." + } + + isConnecting = false + } + + private func parseConfig() throws -> ServerConfig { + var raw = urlText.trimmingCharacters(in: .whitespacesAndNewlines) + if !raw.hasPrefix("http://") && !raw.hasPrefix("https://") { + raw = "https://" + raw + } + guard let comps = URLComponents(string: raw), + let host = comps.host, !host.isEmpty else { + throw URLError(.badURL) + } + return ServerConfig( + host: host, + port: comps.port, + path: comps.path.hasSuffix("/") ? String(comps.path.dropLast()) : comps.path, + token: token.trimmingCharacters(in: .whitespacesAndNewlines), + useHttps: comps.scheme == "https" + ) + } +} diff --git a/Marks/Views/SearchView.swift b/Marks/Views/SearchView.swift new file mode 100644 index 0000000..4ab1b8d --- /dev/null +++ b/Marks/Views/SearchView.swift @@ -0,0 +1,87 @@ +import SwiftUI + +struct SearchView: View { + @Bindable var viewModel: BookmarksViewModel + @Environment(\.openURL) private var openURL + + @State private var searchText = "" + @State private var useSemanticSearch = false + @State private var semanticResults: [Bookmark]? = nil + @State private var searchTask: Task? + + var body: some View { + NavigationStack { + List { + ForEach(results) { bookmark in + BookmarkRow(bookmark: bookmark) + .onTapGesture { + if let url = URL(string: bookmark.url) { openURL(url) } + } + .listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) + .listRowSeparator(.visible) + .swipeActions(edge: .trailing, allowsFullSwipe: true) { + Button(role: .destructive) { + Task { await viewModel.delete(bookmark) } + } label: { + Label("Delete", systemImage: "trash") + } + } + } + } + .listStyle(.plain) + .navigationTitle("Search") + .toolbar { + if viewModel.claude != nil { + ToolbarItem(placement: .topBarTrailing) { + Toggle(isOn: $useSemanticSearch) { + Label("Semantic", systemImage: "sparkles") + } + .toggleStyle(.button) + .onChange(of: useSemanticSearch) { _, _ in scheduleSearch() } + } + } + } + .overlay { + if searchText.isEmpty { + ContentUnavailableView("Search Bookmarks", systemImage: "magnifyingglass", description: Text("Search by title, URL, or tag.")) + } else if results.isEmpty && !viewModel.isLoading { + ContentUnavailableView.search(text: searchText) + } + if viewModel.isLoading { + ProgressView() + } + } + } + .searchable(text: $searchText, prompt: "Titles, URLs, tags…") + .onChange(of: searchText) { _, _ in scheduleSearch() } + } + + private var results: [Bookmark] { + if let semantic = semanticResults { return semantic } + guard !searchText.isEmpty else { return [] } + let q = searchText.lowercased() + return viewModel.bookmarks.filter { b in + b.displayTitle.lowercased().contains(q) || + b.url.lowercased().contains(q) || + b.tagNames.contains { $0.lowercased().contains(q) } || + (b.aiTags ?? []).contains { $0.lowercased().contains(q) } || + (b.aiSummary ?? "").lowercased().contains(q) + } + } + + private func scheduleSearch() { + semanticResults = nil + searchTask?.cancel() + guard !searchText.isEmpty, useSemanticSearch, let claude = viewModel.claude else { return } + searchTask = Task { + try? await Task.sleep(for: .milliseconds(500)) + guard !Task.isCancelled else { return } + let q = searchText + let all = viewModel.bookmarks + do { + let ranked = try await claude.semanticSearch(query: q, in: all) + await MainActor.run { semanticResults = ranked } + } catch {} + } + } +} diff --git a/Marks/Views/SettingsView.swift b/Marks/Views/SettingsView.swift new file mode 100644 index 0000000..208b542 --- /dev/null +++ b/Marks/Views/SettingsView.swift @@ -0,0 +1,58 @@ +import SwiftUI + +struct SettingsView: View { + @Bindable var viewModel: BookmarksViewModel + let onDisconnect: () -> Void + + @State private var claudeKey = UserDefaults.standard.string(forKey: ClaudeService.defaultsKey) ?? "" + @Environment(\.dismiss) private var dismiss + + var body: some View { + NavigationStack { + List { + Section("AI Features") { + VStack(alignment: .leading, spacing: 6) { + Text("OpenRouter API Key") + .font(.system(size: 13, weight: .medium)) + .foregroundStyle(.secondary) + SecureField("sk-or-…", text: $claudeKey) + .textContentType(.password) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + .onChange(of: claudeKey) { _, new in + ClaudeService.save(apiKey: new) + viewModel.updateClaude(new.isEmpty ? nil : ClaudeService(apiKey: new)) + } + } + .padding(.vertical, 4) + + if viewModel.claude != nil { + Label("AI enabled — semantic search, auto-tagging, and smart collections active.", systemImage: "sparkles") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + } else { + Text("Add an OpenRouter API key to enable AI features. Uses Gemini 2.0 Flash Lite — very cheap.") + .font(.system(size: 13)) + .foregroundStyle(.secondary) + } + } + + Section("Server") { + Button(role: .destructive) { + dismiss() + onDisconnect() + } label: { + Label("Disconnect", systemImage: "person.crop.circle.badge.minus") + } + } + } + .navigationTitle("Settings") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } + } + } + } +} diff --git a/Marks/Views/TagsView.swift b/Marks/Views/TagsView.swift new file mode 100644 index 0000000..4d33983 --- /dev/null +++ b/Marks/Views/TagsView.swift @@ -0,0 +1,94 @@ +import SwiftUI + +struct TagsView: View { + @Bindable var viewModel: BookmarksViewModel + + var body: some View { + NavigationStack { + List { + ForEach(allTags, id: \.tag) { entry in + NavigationLink { + TagBookmarksView(tag: entry.tag, viewModel: viewModel) + } label: { + HStack { + Text(entry.tag) + .font(.system(size: 17)) + Spacer() + Text("\(entry.count)") + .font(.system(size: 15)) + .foregroundStyle(.secondary) + } + } + } + } + .navigationTitle("Tags") + .overlay { + if viewModel.bookmarks.isEmpty { + ContentUnavailableView("No Tags", systemImage: "tag", description: Text("Tags from your bookmarks will appear here.")) + } + } + } + } + + private var allTags: [(tag: String, count: Int)] { + var counts: [String: Int] = [:] + for bookmark in viewModel.bookmarks { + for tag in bookmark.tagNames { + counts[tag, default: 0] += 1 + } + for tag in bookmark.aiTags ?? [] where !bookmark.tagNames.contains(tag) { + counts[tag, default: 0] += 1 + } + } + return counts.map { (tag: $0.key, count: $0.value) } + .sorted { $0.count != $1.count ? $0.count > $1.count : $0.tag < $1.tag } + } +} + +struct TagBookmarksView: View { + let tag: String + @Bindable var viewModel: BookmarksViewModel + @Environment(\.openURL) private var openURL + + var body: some View { + List { + ForEach(filteredBookmarks) { bookmark in + BookmarkRow(bookmark: bookmark) + .onTapGesture { + if let url = URL(string: bookmark.url) { openURL(url) } + } + .listRowInsets(EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20)) + .listRowSeparator(.visible) + .swipeActions(edge: .trailing, allowsFullSwipe: true) { + Button(role: .destructive) { + Task { await viewModel.delete(bookmark) } + } label: { + Label("Delete", systemImage: "trash") + } + } + .swipeActions(edge: .leading) { + Button { + Task { await viewModel.archive(bookmark) } + } label: { + Label("Archive", systemImage: "archivebox") + } + .tint(.orange) + } + } + } + .listStyle(.plain) + .navigationTitle(tag) + .navigationBarTitleDisplayMode(.large) + .overlay { + if filteredBookmarks.isEmpty { + ContentUnavailableView("No Bookmarks", systemImage: "tag") + } + } + } + + private var filteredBookmarks: [Bookmark] { + viewModel.bookmarks.filter { + $0.tagNames.contains(tag) || ($0.aiTags ?? []).contains(tag) + } + } +} diff --git a/README.md b/README.md index 99fc95e..80da512 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,69 @@ -

- -

+# Marks -

- Linkdy is a Linkding client created with Flutter. Linkding is a self hosted bookmark manager. The objective of this project is to give all it's users an application to manage the bookmarks from a mobile device. -

+A native iOS client for [linkding](https://github.com/sissbruecker/linkding), the self-hosted bookmark manager. -

- - - - - - -

+Built from scratch in SwiftUI targeting iOS 26. Replaces the previous Flutter-based app. -### Main features -
    -
  • List your bookmarks.
  • -
  • Open the links on an internal browser.
  • -
  • Search bookmarks.
  • -
  • Create new bookmarks.
  • -
  • Create new tags.
  • -
  • List the bookmarks associated with each tag.
  • -
  • Material You interface with dynamic theming (only Android 12+).
  • -
+## Features -## Privacy policy -Check the privacy policy [here](https://pastebin.com/raw/Yiw4h6KK). +- Browse and search your bookmarks +- Swipe to delete or archive +- Add bookmarks manually +- Share to Marks from any app (share extension) +- Tag browser — see all tags sorted by count, tap to filter +- Native search tab with instant client-side filtering +- AI enrichment via OpenRouter — auto-generates summaries and tags for each bookmark +- Semantic search — rank bookmarks by relevance using AI +- Smart Collections — AI groups your bookmarks into themed collections +- Pagination — loads more as you scroll -### Development -1. Clone this repository. -2. Run ``flutter pub get`` to install all the dependencies. -3. Run the application on the desired virtual or physical device. +## Requirements -

- State manager -
- Linkdy uses Riverpod as the state management system. Files ended on .g.dart are auto generated by Riverpod's code generator and shouldn't be edited manually. - The code generator can be started by running dart run build_runner watch. Then, the process will start on the terminal. -

-

- Translations -
- Linkdy uses slang to manage the translations of the application. To add a new translation, create a new file on lib/i18n, with the structure strings_[lang_code].i18n.json. When adding a new string, make sure to add the translation on all .i18n.json files. Then, run dart run slang to generate the translations. -

+- iOS 26+ +- A running [linkding](https://github.com/sissbruecker/linkding) instance with API access +- (Optional) An [OpenRouter](https://openrouter.ai) API key for AI features -### Android signing -1. Clone ``android/key.properties.sample`` and rename it to ``key.properties``. -2. Fill the variables with the values. -3. Put your ``keystore.jks`` file inside ``android/app/``. -4. Run ``flutter build apk --release`` or ``flutter build appbundle --release`` to compile and sign the production build. +## AI Features -
-
-
-
-
+All AI features are optional and powered by [OpenRouter](https://openrouter.ai) using `google/gemini-2.0-flash-lite-001` — one of the cheapest available models (~$0.075/M input tokens). -##### Created by JGeek00 \ No newline at end of file +| Feature | What it does | +|---|---| +| Auto-enrichment | Generates a one-sentence summary and 3-5 tags for each bookmark | +| Semantic search | Ranks your bookmarks by relevance to a natural language query | +| Smart Collections | Groups up to 150 bookmarks into 3-6 themed collections | + +Add your OpenRouter API key in Settings to enable these features. + +## Building + +Requires [xcodegen](https://github.com/yonaskolb/XcodeGen). + +```bash +brew install xcodegen +xcodegen generate +open Marks.xcodeproj +``` + +Then build and run in Xcode. The project uses automatic signing — set your development team in `project.yml` under `DEVELOPMENT_TEAM`. + +## Architecture + +- **SwiftUI** with `@Observable` and `@MainActor` throughout (Swift 6 strict concurrency) +- **LinkdingAPI** — thin wrapper around the linkding REST API +- **ClaudeService** — OpenRouter client for AI enrichment, semantic search, and collections +- **BookmarksViewModel** — central state: bookmarks list, pagination, search, enrichment progress +- **App Groups** — share extension and main app share credentials via `group.com.magicive.marks` +- **UserDefaults** — AI summaries and tags cached locally by bookmark ID + +## Project structure + +``` +Marks/ + Models/ Bookmark, ServerConfig, SmartCollection + Services/ LinkdingAPI, ClaudeService + Views/ BookmarksView, TagsView, SearchView, SettingsView, … + Assets.xcassets App icon and assets +ShareExtension/ iOS share extension (zero-tap bookmark saving) +project.yml xcodegen project spec +``` diff --git a/ShareExtension/Info.plist b/ShareExtension/Info.plist new file mode 100644 index 0000000..a23113c --- /dev/null +++ b/ShareExtension/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDisplayName + Marks + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionAttributes + + NSExtensionActivationRule + TRUEPREDICATE + + NSExtensionPointIdentifier + com.apple.share-services + NSExtensionPrincipalClass + ShareViewController + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ShareExtension/ShareExtension.entitlements similarity index 62% rename from ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to ShareExtension/ShareExtension.entitlements index 18d9810..02a7360 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/ShareExtension/ShareExtension.entitlements @@ -2,7 +2,9 @@ - IDEDidComputeMac32BitWarning - + com.apple.security.application-groups + + group.com.magicive.marks + diff --git a/ShareExtension/ShareViewController.swift b/ShareExtension/ShareViewController.swift new file mode 100644 index 0000000..ca147a8 --- /dev/null +++ b/ShareExtension/ShareViewController.swift @@ -0,0 +1,129 @@ +import UIKit +import UniformTypeIdentifiers + +@objc(ShareViewController) +class ShareViewController: UIViewController { + + private let appGroupId = "group.com.magicive.marks" + private let configKey = "serverConfig" + + override func viewDidLoad() { + super.viewDidLoad() + let blur = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) + blur.frame = view.bounds + blur.autoresizingMask = [.flexibleWidth, .flexibleHeight] + view.addSubview(blur) + extractURLAndSave() + } + + private func extractURLAndSave() { + guard let item = extensionContext?.inputItems.first as? NSExtensionItem, + let attachments = item.attachments else { + showResult(success: false, message: "Nothing to save") + return + } + + func load(typeId: String) -> Bool { + guard let attachment = attachments.first(where: { $0.hasItemConformingToTypeIdentifier(typeId) }) else { + return false + } + attachment.loadItem(forTypeIdentifier: typeId, options: nil) { [weak self] item, _ in + let urlString = typeId == UTType.url.identifier + ? ((item as? URL)?.absoluteString ?? (item as? String)) + : (item as? String) + DispatchQueue.main.async { + if let url = urlString { self?.save(url: url) } + else { self?.showResult(success: false, message: "No URL found") } + } + } + return true + } + + if !load(typeId: UTType.url.identifier) && !load(typeId: UTType.plainText.identifier) { + showResult(success: false, message: "No URL found") + } + } + + private func save(url: String) { + guard let groupDefaults = UserDefaults(suiteName: appGroupId), + let data = groupDefaults.data(forKey: configKey), + let config = try? JSONSerialization.jsonObject(with: data) as? [String: Any], + let host = config["host"] as? String, + let token = config["token"] as? String, + let useHttps = config["useHttps"] as? Bool else { + showResult(success: false, message: "Open Marks first") + return + } + + var base = (useHttps ? "https" : "http") + "://" + host + if let port = config["port"] as? Int { base += ":\(port)" } + if let path = config["path"] as? String, !path.isEmpty { base += path } + + guard let apiUrl = URL(string: "\(base)/api/bookmarks/") else { + showResult(success: false, message: "Bad server URL") + return + } + + var req = URLRequest(url: apiUrl) + req.httpMethod = "POST" + req.setValue("Token \(token)", forHTTPHeaderField: "Authorization") + req.setValue("application/json", forHTTPHeaderField: "Content-Type") + req.httpBody = try? JSONSerialization.data(withJSONObject: [ + "url": url, "is_archived": false, "unread": false, "shared": false + ]) + + URLSession.shared.dataTask(with: req) { [weak self] _, response, error in + DispatchQueue.main.async { + let code = (response as? HTTPURLResponse)?.statusCode ?? 0 + let ok = error == nil && (code == 200 || code == 201) + self?.showResult(success: ok, message: ok ? "Bookmarked" : "Failed to save") + } + }.resume() + } + + private func showResult(success: Bool, message: String) { + let card = UIView() + card.backgroundColor = success ? .systemGreen : .systemRed + card.layer.cornerRadius = 16 + card.layer.cornerCurve = .continuous + card.translatesAutoresizingMaskIntoConstraints = false + card.alpha = 0 + + let stack = UIStackView() + stack.axis = .horizontal + stack.spacing = 10 + stack.alignment = .center + stack.translatesAutoresizingMaskIntoConstraints = false + + let icon = UIImageView(image: UIImage(systemName: success ? "checkmark.circle.fill" : "xmark.circle.fill")) + icon.tintColor = .white + icon.preferredSymbolConfiguration = .init(pointSize: 22, weight: .semibold) + + let label = UILabel() + label.text = message + label.textColor = .white + label.font = .systemFont(ofSize: 17, weight: .semibold) + + stack.addArrangedSubview(icon) + stack.addArrangedSubview(label) + card.addSubview(stack) + view.addSubview(card) + + NSLayoutConstraint.activate([ + stack.centerXAnchor.constraint(equalTo: card.centerXAnchor), + stack.centerYAnchor.constraint(equalTo: card.centerYAnchor), + stack.leadingAnchor.constraint(greaterThanOrEqualTo: card.leadingAnchor, constant: 24), + card.centerXAnchor.constraint(equalTo: view.centerXAnchor), + card.centerYAnchor.constraint(equalTo: view.centerYAnchor), + card.heightAnchor.constraint(equalToConstant: 56), + card.widthAnchor.constraint(greaterThanOrEqualToConstant: 180), + ]) + + UIView.animate(withDuration: 0.2) { card.alpha = 1 } + DispatchQueue.main.asyncAfter(deadline: .now() + (success ? 0.8 : 2.0)) { [weak self] in + UIView.animate(withDuration: 0.15, animations: { card.alpha = 0 }) { _ in + self?.extensionContext?.completeRequest(returningItems: [], completionHandler: nil) + } + } + } +} diff --git a/analysis_options.yaml b/analysis_options.yaml deleted file mode 100644 index 6c65d51..0000000 --- a/analysis_options.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - require_trailing_commas: true - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index be3943c..0000000 --- a/android/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts deleted file mode 100644 index 9c51069..0000000 --- a/android/app/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -plugins { - id("com.android.application") - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -android { - namespace = "com.jgeek00.linkdy" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.jgeek00.linkdy" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -flutter { - source = "../.." -} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 5d15d09..0000000 --- a/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/jgeek00/linkdy/MainActivity.kt b/android/app/src/main/kotlin/com/jgeek00/linkdy/MainActivity.kt deleted file mode 100644 index 06b45b3..0000000 --- a/android/app/src/main/kotlin/com/jgeek00/linkdy/MainActivity.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.jgeek00.linkdy - - -import android.content.Intent -import androidx.annotation.NonNull; -import io.flutter.embedding.android.FlutterActivity -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugins.GeneratedPluginRegistrant -import android.os.Bundle - -class MainActivity: FlutterActivity() { - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine); - java.lang.Thread.sleep(1000); - } - override fun onCreate(savedInstanceState: Bundle?) { - if (intent.getIntExtra("org.chromium.chrome.extra.TASK_ID", -1) == this.taskId) { - this.finish() - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - } - super.onCreate(savedInstanceState) - } -} - diff --git a/android/app/src/main/res/drawable-hdpi/android12splash.png b/android/app/src/main/res/drawable-hdpi/android12splash.png deleted file mode 100644 index 11baaa7..0000000 Binary files a/android/app/src/main/res/drawable-hdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png deleted file mode 100644 index 11baaa7..0000000 Binary files a/android/app/src/main/res/drawable-hdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/android12splash.png b/android/app/src/main/res/drawable-mdpi/android12splash.png deleted file mode 100644 index 2c36611..0000000 Binary files a/android/app/src/main/res/drawable-mdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-mdpi/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png deleted file mode 100644 index 2c36611..0000000 Binary files a/android/app/src/main/res/drawable-mdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-hdpi/android12splash.png b/android/app/src/main/res/drawable-night-hdpi/android12splash.png deleted file mode 100644 index 11baaa7..0000000 Binary files a/android/app/src/main/res/drawable-night-hdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-hdpi/splash.png b/android/app/src/main/res/drawable-night-hdpi/splash.png deleted file mode 100644 index 11baaa7..0000000 Binary files a/android/app/src/main/res/drawable-night-hdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-mdpi/android12splash.png b/android/app/src/main/res/drawable-night-mdpi/android12splash.png deleted file mode 100644 index 2c36611..0000000 Binary files a/android/app/src/main/res/drawable-night-mdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-mdpi/splash.png b/android/app/src/main/res/drawable-night-mdpi/splash.png deleted file mode 100644 index 2c36611..0000000 Binary files a/android/app/src/main/res/drawable-night-mdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-v21/background.png b/android/app/src/main/res/drawable-night-v21/background.png deleted file mode 100644 index bb72a79..0000000 Binary files a/android/app/src/main/res/drawable-night-v21/background.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-v21/launch_background.xml b/android/app/src/main/res/drawable-night-v21/launch_background.xml deleted file mode 100644 index 3cc4948..0000000 --- a/android/app/src/main/res/drawable-night-v21/launch_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png deleted file mode 100644 index 89b5db4..0000000 Binary files a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-xhdpi/splash.png b/android/app/src/main/res/drawable-night-xhdpi/splash.png deleted file mode 100644 index 89b5db4..0000000 Binary files a/android/app/src/main/res/drawable-night-xhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png deleted file mode 100644 index fca642b..0000000 Binary files a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi/splash.png b/android/app/src/main/res/drawable-night-xxhdpi/splash.png deleted file mode 100644 index fca642b..0000000 Binary files a/android/app/src/main/res/drawable-night-xxhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png deleted file mode 100755 index c17ea0c..0000000 Binary files a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/splash.png deleted file mode 100755 index c17ea0c..0000000 Binary files a/android/app/src/main/res/drawable-night-xxxhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night/background.png b/android/app/src/main/res/drawable-night/background.png deleted file mode 100644 index bb72a79..0000000 Binary files a/android/app/src/main/res/drawable-night/background.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-night/launch_background.xml b/android/app/src/main/res/drawable-night/launch_background.xml deleted file mode 100644 index 3cc4948..0000000 --- a/android/app/src/main/res/drawable-night/launch_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/android/app/src/main/res/drawable-v21/background.png b/android/app/src/main/res/drawable-v21/background.png deleted file mode 100644 index 3107d37..0000000 Binary files a/android/app/src/main/res/drawable-v21/background.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index 3cc4948..0000000 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/android/app/src/main/res/drawable-xhdpi/android12splash.png b/android/app/src/main/res/drawable-xhdpi/android12splash.png deleted file mode 100644 index 89b5db4..0000000 Binary files a/android/app/src/main/res/drawable-xhdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png deleted file mode 100644 index 89b5db4..0000000 Binary files a/android/app/src/main/res/drawable-xhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxhdpi/android12splash.png deleted file mode 100644 index fca642b..0000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png deleted file mode 100644 index fca642b..0000000 Binary files a/android/app/src/main/res/drawable-xxhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png deleted file mode 100755 index c17ea0c..0000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png deleted file mode 100755 index c17ea0c..0000000 Binary files a/android/app/src/main/res/drawable-xxxhdpi/splash.png and /dev/null differ diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png deleted file mode 100644 index 3107d37..0000000 Binary files a/android/app/src/main/res/drawable/background.png and /dev/null differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 3cc4948..0000000 --- a/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 4f6dce4..0000000 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09b..0000000 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 3c6ecb0..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index b7d45a5..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png deleted file mode 100644 index dbdb6bb..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index fa90d39..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 9e1c1ba..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 0f19c5d..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png deleted file mode 100644 index 52927cc..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 64b2236..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 0284c77..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 8c565cb..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png deleted file mode 100644 index e7fb430..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index b03c0fc..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index b6aa604..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 4ae93d2..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png deleted file mode 100644 index 0742140..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 33c85b2..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b377c18..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 83bd06d..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png deleted file mode 100644 index 6625500..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4fa4d38..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml deleted file mode 100644 index 09f904c..0000000 --- a/android/app/src/main/res/values-night-v31/styles.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index dbc9ea9..0000000 --- a/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/values-v31/styles.xml b/android/app/src/main/res/values-v31/styles.xml deleted file mode 100644 index e437c38..0000000 --- a/android/app/src/main/res/values-v31/styles.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml deleted file mode 100644 index 1d0f3da..0000000 --- a/android/app/src/main/res/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #5856E0 - \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 0d1fa8f..0000000 --- a/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/android/build.gradle.kts b/android/build.gradle.kts deleted file mode 100644 index dbee657..0000000 --- a/android/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index fbee1d8..0000000 --- a/android/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e4ef43f..0000000 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/android/key.properties.sample b/android/key.properties.sample deleted file mode 100644 index b51dc2c..0000000 --- a/android/key.properties.sample +++ /dev/null @@ -1,4 +0,0 @@ -storePassword= # keystore password # -keyPassword= # keystore key password # -keyAlias= # key alias # -storeFile= # ./keystore-file-name.jks # \ No newline at end of file diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts deleted file mode 100644 index ca7fe06..0000000 --- a/android/settings.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false -} - -include(":app") diff --git a/assets/icon/icon-splash.png b/assets/icon/icon-splash.png deleted file mode 100755 index 14d4f3e..0000000 Binary files a/assets/icon/icon-splash.png and /dev/null differ diff --git a/assets/icon/icon1024-background.png b/assets/icon/icon1024-background.png deleted file mode 100755 index c23e2be..0000000 Binary files a/assets/icon/icon1024-background.png and /dev/null differ diff --git a/assets/icon/icon1024.png b/assets/icon/icon1024.png deleted file mode 100755 index 25fb489..0000000 Binary files a/assets/icon/icon1024.png and /dev/null differ diff --git a/assets/other/banner.png b/assets/other/banner.png deleted file mode 100644 index 3dde801..0000000 Binary files a/assets/other/banner.png and /dev/null differ diff --git a/assets/other/get-appstore.png b/assets/other/get-appstore.png deleted file mode 100644 index 157e238..0000000 Binary files a/assets/other/get-appstore.png and /dev/null differ diff --git a/assets/other/get-github.png b/assets/other/get-github.png deleted file mode 100644 index f869aa5..0000000 Binary files a/assets/other/get-github.png and /dev/null differ diff --git a/assets/other/get_google_play.png b/assets/other/get_google_play.png deleted file mode 100644 index c77b746..0000000 Binary files a/assets/other/get_google_play.png and /dev/null differ diff --git a/assets/resources/github.svg b/assets/resources/github.svg deleted file mode 100644 index 25d9004..0000000 --- a/assets/resources/github.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/resources/google-play.svg b/assets/resources/google-play.svg deleted file mode 100644 index eda3968..0000000 --- a/assets/resources/google-play.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/devtools_options.yaml b/devtools_options.yaml deleted file mode 100644 index fa0b357..0000000 --- a/devtools_options.yaml +++ /dev/null @@ -1,3 +0,0 @@ -description: This file stores settings for Dart & Flutter DevTools. -documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states -extensions: diff --git a/ios/.gitignore b/ios/.gitignore deleted file mode 100644 index 7a7f987..0000000 --- a/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 391a902..0000000 --- a/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - - diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6..0000000 --- a/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bf..0000000 --- a/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile deleted file mode 100644 index 7172f02..0000000 --- a/ios/Podfile +++ /dev/null @@ -1,46 +0,0 @@ -# Uncomment this line to define a global platform for your project -platform :ios, '14.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - - # Share Extension is name of Extension which you created which is in this case 'Share Extension' - target 'Share Extension' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/ios/Podfile.lock b/ios/Podfile.lock deleted file mode 100644 index ea4f7c2..0000000 --- a/ios/Podfile.lock +++ /dev/null @@ -1,80 +0,0 @@ -PODS: - - Flutter (1.0.0) - - flutter_custom_tabs_ios (2.5.0): - - Flutter - - flutter_native_splash (2.4.3): - - Flutter - - listen_sharing_intent (1.9.2): - - Flutter - - package_info_plus (0.4.5): - - Flutter - - Sentry/HybridSDK (8.58.2) - - sentry_flutter (9.20.0): - - Flutter - - FlutterMacOS - - Sentry/HybridSDK (= 8.58.2) - - share_plus (0.0.1): - - Flutter - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - url_launcher_ios (0.0.1): - - Flutter - - webview_flutter_wkwebview (0.0.1): - - Flutter - - FlutterMacOS - -DEPENDENCIES: - - Flutter (from `Flutter`) - - flutter_custom_tabs_ios (from `.symlinks/plugins/flutter_custom_tabs_ios/ios`) - - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - - listen_sharing_intent (from `.symlinks/plugins/listen_sharing_intent/ios`) - - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`) - - share_plus (from `.symlinks/plugins/share_plus/ios`) - - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`) - -SPEC REPOS: - trunk: - - Sentry - -EXTERNAL SOURCES: - Flutter: - :path: Flutter - flutter_custom_tabs_ios: - :path: ".symlinks/plugins/flutter_custom_tabs_ios/ios" - flutter_native_splash: - :path: ".symlinks/plugins/flutter_native_splash/ios" - listen_sharing_intent: - :path: ".symlinks/plugins/listen_sharing_intent/ios" - package_info_plus: - :path: ".symlinks/plugins/package_info_plus/ios" - sentry_flutter: - :path: ".symlinks/plugins/sentry_flutter/ios" - share_plus: - :path: ".symlinks/plugins/share_plus/ios" - shared_preferences_foundation: - :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - webview_flutter_wkwebview: - :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" - -SPEC CHECKSUMS: - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_custom_tabs_ios: 706423b5f8773208a87b2e5a5ba757a899ed7cbd - flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 - listen_sharing_intent: 74a842adcbcf7bedf7bbc938c749da9155141b9a - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - Sentry: de29b881e83bd91cf99a927f82f1fd86bfb39db2 - sentry_flutter: aafdf112550e9550972852e71f44994bd4239254 - share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 - url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa - webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4 - -PODFILE CHECKSUM: f4a1a94f7b997c60f34f5ec510acd4c2ebcd8b70 - -COCOAPODS: 1.16.2 diff --git a/ios/PrivacyInfo.xcprivacy b/ios/PrivacyInfo.xcprivacy deleted file mode 100644 index dd6881b..0000000 --- a/ios/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,17 +0,0 @@ - - - - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - 1C8F.1 - - - - - diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 4e654ac..0000000 --- a/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,981 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 0D8852512BB0F5320049FE7A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0D88524F2BB0F36E0049FE7A /* PrivacyInfo.xcprivacy */; }; - 0D88526A2BB1B4910049FE7A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0D88524F2BB0F36E0049FE7A /* PrivacyInfo.xcprivacy */; }; - 0D88526B2BB1B4920049FE7A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0D88524F2BB0F36E0049FE7A /* PrivacyInfo.xcprivacy */; }; - 0DD98D4C2BAE797F00804BE7 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DD98D4B2BAE797F00804BE7 /* ShareViewController.swift */; }; - 0DD98D4F2BAE797F00804BE7 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 0DD98D4E2BAE797F00804BE7 /* Base */; }; - 0DD98D532BAE797F00804BE7 /* Share Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 0DD98D492BAE797F00804BE7 /* Share Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 1E57812B8C12FEC8D79AD975 /* Pods_Share_Extension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D82812D4EFCC75C7B0FDB517 /* Pods_Share_Extension.framework */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 8ED8683A9B75B252533F9969 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4533A4D5154C6705434104C /* Pods_Runner.framework */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 0DD98D512BAE797F00804BE7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 0DD98D482BAE797F00804BE7; - remoteInfo = "Share Extension"; - }; - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 0DD98D542BAE797F00804BE7 /* Embed Foundation Extensions */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 13; - files = ( - 0DD98D532BAE797F00804BE7 /* Share Extension.appex in Embed Foundation Extensions */, - ); - name = "Embed Foundation Extensions"; - runOnlyForDeploymentPostprocessing = 0; - }; - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 028E6C730A588E1E84511D36 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 033AEC9585A60167C7A7CE55 /* Pods-Share Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Share Extension.release.xcconfig"; path = "Target Support Files/Pods-Share Extension/Pods-Share Extension.release.xcconfig"; sourceTree = ""; }; - 0D88524F2BB0F36E0049FE7A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - 0DD98D492BAE797F00804BE7 /* Share Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Share Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 0DD98D4B2BAE797F00804BE7 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; - 0DD98D4E2BAE797F00804BE7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; - 0DD98D502BAE797F00804BE7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 0DD98D592BAE79B700804BE7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - 0DD98D5A2BAE79BE00804BE7 /* Share Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Share Extension.entitlements"; sourceTree = ""; }; - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 67C02B529825EA1C87E41529 /* Pods-Share Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Share Extension.debug.xcconfig"; path = "Target Support Files/Pods-Share Extension/Pods-Share Extension.debug.xcconfig"; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D82812D4EFCC75C7B0FDB517 /* Pods_Share_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Share_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E4533A4D5154C6705434104C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F0C2D0B1825F8EE28A1E5C13 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - F7EBE0A0B68411B7E3F62A40 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - FAF7552BBEA34A8D0259E3C6 /* Pods-Share Extension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Share Extension.profile.xcconfig"; path = "Target Support Files/Pods-Share Extension/Pods-Share Extension.profile.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 0DD98D462BAE797F00804BE7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E57812B8C12FEC8D79AD975 /* Pods_Share_Extension.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 6AD84DA433147BB17C6D6D03 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 8ED8683A9B75B252533F9969 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0DD98D4A2BAE797F00804BE7 /* Share Extension */ = { - isa = PBXGroup; - children = ( - 0DD98D5A2BAE79BE00804BE7 /* Share Extension.entitlements */, - 0DD98D4B2BAE797F00804BE7 /* ShareViewController.swift */, - 0DD98D4D2BAE797F00804BE7 /* MainInterface.storyboard */, - 0DD98D502BAE797F00804BE7 /* Info.plist */, - ); - path = "Share Extension"; - sourceTree = ""; - }; - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 7B599DD5810362B9EDB56A41 /* Frameworks */ = { - isa = PBXGroup; - children = ( - E4533A4D5154C6705434104C /* Pods_Runner.framework */, - D82812D4EFCC75C7B0FDB517 /* Pods_Share_Extension.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 7B83F3B4F4DBEDE770813DD7 /* Pods */ = { - isa = PBXGroup; - children = ( - F0C2D0B1825F8EE28A1E5C13 /* Pods-Runner.debug.xcconfig */, - F7EBE0A0B68411B7E3F62A40 /* Pods-Runner.release.xcconfig */, - 028E6C730A588E1E84511D36 /* Pods-Runner.profile.xcconfig */, - 67C02B529825EA1C87E41529 /* Pods-Share Extension.debug.xcconfig */, - 033AEC9585A60167C7A7CE55 /* Pods-Share Extension.release.xcconfig */, - FAF7552BBEA34A8D0259E3C6 /* Pods-Share Extension.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 0D88524F2BB0F36E0049FE7A /* PrivacyInfo.xcprivacy */, - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 0DD98D4A2BAE797F00804BE7 /* Share Extension */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - 7B83F3B4F4DBEDE770813DD7 /* Pods */, - 7B599DD5810362B9EDB56A41 /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - 0DD98D492BAE797F00804BE7 /* Share Extension.appex */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 0DD98D592BAE79B700804BE7 /* Runner.entitlements */, - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 0DD98D482BAE797F00804BE7 /* Share Extension */ = { - isa = PBXNativeTarget; - buildConfigurationList = 0DD98D582BAE797F00804BE7 /* Build configuration list for PBXNativeTarget "Share Extension" */; - buildPhases = ( - 1CD2B5D70FA0C78B9CD70358 /* [CP] Check Pods Manifest.lock */, - 0DD98D452BAE797F00804BE7 /* Sources */, - 0DD98D462BAE797F00804BE7 /* Frameworks */, - 0DD98D472BAE797F00804BE7 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Share Extension"; - productName = "Share Extension"; - productReference = 0DD98D492BAE797F00804BE7 /* Share Extension.appex */; - productType = "com.apple.product-type.app-extension"; - }; - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - 6AD84DA433147BB17C6D6D03 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 9A63071FDE5E8B0372DC7C6D /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 0DD98D542BAE797F00804BE7 /* Embed Foundation Extensions */, - 9A635442A56AC99A9E0267CA /* [CP] Embed Pods Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - ); - buildRules = ( - ); - dependencies = ( - 0DD98D522BAE797F00804BE7 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 1530; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 0DD98D482BAE797F00804BE7 = { - CreatedOnToolsVersion = 15.3; - }; - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - 0DD98D482BAE797F00804BE7 /* Share Extension */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 0DD98D472BAE797F00804BE7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0D88526A2BB1B4910049FE7A /* PrivacyInfo.xcprivacy in Resources */, - 0DD98D4F2BAE797F00804BE7 /* Base in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0D88526B2BB1B4920049FE7A /* PrivacyInfo.xcprivacy in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 0D8852512BB0F5320049FE7A /* PrivacyInfo.xcprivacy in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 1CD2B5D70FA0C78B9CD70358 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Share Extension-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - 9A63071FDE5E8B0372DC7C6D /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9A635442A56AC99A9E0267CA /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 0DD98D452BAE797F00804BE7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0DD98D4C2BAE797F00804BE7 /* ShareViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 0DD98D522BAE797F00804BE7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 0DD98D482BAE797F00804BE7 /* Share Extension */; - targetProxy = 0DD98D512BAE797F00804BE7 /* PBXContainerItemProxy */; - }; - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 0DD98D4D2BAE797F00804BE7 /* MainInterface.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 0DD98D4E2BAE797F00804BE7 /* Base */, - ); - name = MainInterface.storyboard; - sourceTree = ""; - }; - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 0DD98D552BAE797F00804BE7 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 67C02B529825EA1C87E41529 /* Pods-Share Extension.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - CUSTOM_GROUP_ID = group.com.jgeek00.linkdy; - DEVELOPMENT_TEAM = 38Z3B9TJTR; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Share Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Share Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.linkdy.Share-Extension"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_ENABLE_EXPLICIT_MODULES = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 0DD98D562BAE797F00804BE7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 033AEC9585A60167C7A7CE55 /* Pods-Share Extension.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - CUSTOM_GROUP_ID = group.com.jgeek00.linkdy; - DEVELOPMENT_TEAM = 38Z3B9TJTR; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Share Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Share Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.linkdy.Share-Extension"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_ENABLE_EXPLICIT_MODULES = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 0DD98D572BAE797F00804BE7 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FAF7552BBEA34A8D0259E3C6 /* Pods-Share Extension.profile.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - CUSTOM_GROUP_ID = group.com.jgeek00.linkdy; - DEVELOPMENT_TEAM = 38Z3B9TJTR; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "Share Extension/Info.plist"; - INFOPLIST_KEY_CFBundleDisplayName = "Share Extension"; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MARKETING_VERSION = 1.0; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.jgeek00.linkdy.Share-Extension"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_ENABLE_EXPLICIT_MODULES = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Profile; - }; - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - CUSTOM_GROUP_ID = group.com.jgeek00.linkdy; - DEVELOPMENT_TEAM = 38Z3B9TJTR; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = Linkdy; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.linkdy; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.myLinkding.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.myLinkding.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.myLinkding.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - CUSTOM_GROUP_ID = group.com.jgeek00.linkdy; - DEVELOPMENT_TEAM = 38Z3B9TJTR; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = Linkdy; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.linkdy; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - CUSTOM_GROUP_ID = group.com.jgeek00.linkdy; - DEVELOPMENT_TEAM = 38Z3B9TJTR; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = Linkdy; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.jgeek00.linkdy; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 0DD98D582BAE797F00804BE7 /* Build configuration list for PBXNativeTarget "Share Extension" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0DD98D552BAE797F00804BE7 /* Debug */, - 0DD98D562BAE797F00804BE7 /* Release */, - 0DD98D572BAE797F00804BE7 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc1..0000000 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift deleted file mode 100644 index c30b367..0000000 --- a/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } - - func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { - GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) - } -} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fa..0000000 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index ed114a3..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 1041500..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 3f99a9f..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index c5e54f1..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 20e36bf..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index de4dc09..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 5ead188..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 3f99a9f..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 31387f9..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 8698069..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png deleted file mode 100644 index 41c36f2..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png deleted file mode 100644 index db53296..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png deleted file mode 100644 index 6c6aae9..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png deleted file mode 100644 index cc6bb37..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 8698069..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 0d14a8f..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png deleted file mode 100644 index ffe6310..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png deleted file mode 100644 index fca922d..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 1789406..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 1998078..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 19de968..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json deleted file mode 100644 index 8bb185b..0000000 --- a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "filename" : "background.png", - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "darkbackground.png", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png deleted file mode 100644 index 3107d37..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png deleted file mode 100644 index bb72a79..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index f3387d4..0000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "images" : [ - { - "filename" : "LaunchImage.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "LaunchImageDark.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "LaunchImage@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "LaunchImageDark@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "LaunchImage@3x.png", - "idiom" : "universal", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "LaunchImageDark@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 2c36611..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 89b5db4..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index fca642b..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png deleted file mode 100644 index 2c36611..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png deleted file mode 100644 index 89b5db4..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png deleted file mode 100644 index fca642b..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725..0000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index d88ac8a..0000000 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c2851..0000000 --- a/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist deleted file mode 100644 index feb386c..0000000 --- a/ios/Runner/Info.plist +++ /dev/null @@ -1,95 +0,0 @@ - - - - - AppGroupId - $(CUSTOM_GROUP_ID) - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Linkdy - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleLocalizations - - en - es - - CFBundleName - linkdy - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLSchemes - - ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER) - - - - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneClassName - UIWindowScene - UISceneConfigurationName - flutter - UISceneDelegateClassName - FlutterSceneDelegate - UISceneStoryboardFile - Main - - - - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a5..0000000 --- a/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements deleted file mode 100644 index e100544..0000000 --- a/ios/Runner/Runner.entitlements +++ /dev/null @@ -1,20 +0,0 @@ - - - - - aps-environment - development - com.apple.developer.associated-domains - - applinks:example.com - - com.apple.developer.associated-domains - - applinks:example.com - - com.apple.security.application-groups - - group.com.jgeek00.linkdy - - - \ No newline at end of file diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b..0000000 --- a/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/ios/Share Extension/Base.lproj/MainInterface.storyboard b/ios/Share Extension/Base.lproj/MainInterface.storyboard deleted file mode 100644 index 286a508..0000000 --- a/ios/Share Extension/Base.lproj/MainInterface.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/Share Extension/Info.plist b/ios/Share Extension/Info.plist deleted file mode 100644 index 96adeef..0000000 --- a/ios/Share Extension/Info.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - AppGroupId - $(CUSTOM_GROUP_ID) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - NSExtension - - NSExtensionAttributes - - NSExtensionActivationRule - - - NSExtensionActivationSupportsText - - - NSExtensionActivationSupportsWebURLWithMaxCount - 1 - - - NSExtensionMainStoryboard - MainInterface - NSExtensionPointIdentifier - com.apple.share-services - - - \ No newline at end of file diff --git a/ios/Share Extension/ShareViewController.swift b/ios/Share Extension/ShareViewController.swift deleted file mode 100644 index e17690a..0000000 --- a/ios/Share Extension/ShareViewController.swift +++ /dev/null @@ -1,14 +0,0 @@ -// If you get no such module 'listen_sharing_intent' error. -// Go to Build Phases of your Runner target and -// move `Embed Foundation Extension` to the top of `Thin Binary`. -import listen_sharing_intent - -class ShareViewController: RSIShareViewController { - - // Use this method to return false if you don't want to redirect to host app automatically. - // Default is true - override func shouldAutoRedirect() -> Bool { - return false - } - -} \ No newline at end of file diff --git a/lib/config/app_screens.dart b/lib/config/app_screens.dart deleted file mode 100644 index 921abf4..0000000 --- a/lib/config/app_screens.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/models/app_route.dart'; -import 'package:linkdy/router/paths.dart'; - -final appScreens = [ - AppRoute( - icon: Icons.bookmarks_rounded, - route: RoutesPaths.bookmarks, - name: t.bookmarks.bookmarks, - ), - AppRoute( - icon: Icons.label_rounded, - route: RoutesPaths.tags, - name: t.tags.tags, - ), - AppRoute( - icon: Icons.settings_rounded, - route: RoutesPaths.settings, - name: t.settings.settings, - ), -]; diff --git a/lib/config/options.dart b/lib/config/options.dart deleted file mode 100644 index e7b3009..0000000 --- a/lib/config/options.dart +++ /dev/null @@ -1,4 +0,0 @@ -class ConfigOptions { - static const int listLimit = 20; - static const String slidableGroupTag = "bookmarksSlidable"; -} diff --git a/lib/config/sizes.dart b/lib/config/sizes.dart deleted file mode 100644 index ee26a9e..0000000 --- a/lib/config/sizes.dart +++ /dev/null @@ -1,3 +0,0 @@ -class Sizes { - static int tabletBreakpoint = 800; -} diff --git a/lib/config/theme.dart b/lib/config/theme.dart deleted file mode 100644 index 9624553..0000000 --- a/lib/config/theme.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:flutter/material.dart'; - -ThemeData lightTheme(ColorScheme? dynamicColorScheme) => ThemeData( - useMaterial3: true, - colorScheme: dynamicColorScheme, - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), - elevation: 4, - ), - brightness: Brightness.light, - listTileTheme: ListTileThemeData( - tileColor: Colors.transparent, - textColor: - dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), - iconColor: - dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(117, 117, 117, 1), - ), - cardTheme: CardThemeData(surfaceTintColor: dynamicColorScheme?.surfaceTint), - popupMenuTheme: PopupMenuThemeData(surfaceTintColor: dynamicColorScheme?.surfaceTint), - navigationBarTheme: NavigationBarThemeData(surfaceTintColor: dynamicColorScheme?.surfaceTint), - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), - }, - ), - ); - -ThemeData darkTheme(ColorScheme? dynamicColorScheme) => ThemeData( - useMaterial3: true, - colorScheme: dynamicColorScheme, - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), - elevation: 4, - ), - brightness: Brightness.dark, - listTileTheme: ListTileThemeData( - tileColor: Colors.transparent, - textColor: - dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), - iconColor: - dynamicColorScheme != null ? dynamicColorScheme.onSurfaceVariant : const Color.fromRGBO(187, 187, 187, 1), - ), - cardTheme: CardThemeData(surfaceTintColor: dynamicColorScheme?.surfaceTint), - popupMenuTheme: PopupMenuThemeData(surfaceTintColor: dynamicColorScheme?.surfaceTint), - navigationBarTheme: NavigationBarThemeData(surfaceTintColor: dynamicColorScheme?.surfaceTint), - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), - }, - ), - ); - -ThemeData lightThemeOldVersions(MaterialColor primaryColor) => ThemeData( - useMaterial3: true, - colorSchemeSeed: primaryColor, - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), - elevation: 4, - ), - listTileTheme: const ListTileThemeData( - tileColor: Colors.transparent, - textColor: Color.fromRGBO(117, 117, 117, 1), - iconColor: Color.fromRGBO(117, 117, 117, 1), - ), - brightness: Brightness.light, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), - }, - ), - ); - -ThemeData darkThemeOldVersions(MaterialColor primaryColor) => ThemeData( - useMaterial3: true, - colorSchemeSeed: primaryColor, - snackBarTheme: SnackBarThemeData( - contentTextStyle: const TextStyle(color: Colors.white), - behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), - elevation: 4, - ), - listTileTheme: const ListTileThemeData( - tileColor: Colors.transparent, - textColor: Color.fromRGBO(187, 187, 187, 1), - iconColor: Color.fromRGBO(187, 187, 187, 1), - ), - brightness: Brightness.dark, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), - }, - ), - ); diff --git a/lib/constants/colors.dart b/lib/constants/colors.dart deleted file mode 100644 index cfcb19e..0000000 --- a/lib/constants/colors.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:linkdy/constants/linkding_color.dart'; - -const List colors = [ - linkdingColor, - Colors.red, - Colors.green, - Colors.blue, - Colors.yellow, - Colors.orange, - Colors.brown, - Colors.cyan, - Colors.purple, - Colors.pink, - Colors.deepOrange, - Colors.indigo, -]; diff --git a/lib/constants/enums.dart b/lib/constants/enums.dart deleted file mode 100644 index de5ad89..0000000 --- a/lib/constants/enums.dart +++ /dev/null @@ -1,26 +0,0 @@ -enum LoadStatus { loading, loaded, error } - -enum ConnectionMethod { http, https } - -enum SelectedTheme { system, light, dark } - -enum AuthResult { success, invalidToken, other } - -enum FilteredBookmarksMode { tag, shared, archived } - -enum ReadStatus { all, unread, read } - -enum SortingType { date, title } - -enum SortingWay { descendant, ascendant } - -enum OpenLinksBrowser { integrated, browserCustomTab, systemBrowser } - -extension OpenLinksBrowserExtension on OpenLinksBrowser { - static OpenLinksBrowser? fromString(String? value) { - if (value == null || !OpenLinksBrowser.values.map((v) => v.toString()).contains(value)) { - return null; - } - return OpenLinksBrowser.values.firstWhere((e) => e.toString() == value); - } -} diff --git a/lib/constants/global_keys.dart b/lib/constants/global_keys.dart deleted file mode 100644 index 5b5dcc4..0000000 --- a/lib/constants/global_keys.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/material.dart'; - -class ScaffoldMessengerKeys { - static final root = GlobalKey(); - static final onboarding = GlobalKey(); - static final bookmarks = GlobalKey(); - static final search = GlobalKey(); - static final tags = GlobalKey(); - static final addBookmark = GlobalKey(); - static final filteredBookmarks = GlobalKey(); -} diff --git a/lib/constants/linkding_color.dart b/lib/constants/linkding_color.dart deleted file mode 100644 index 142ced7..0000000 --- a/lib/constants/linkding_color.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter/material.dart'; - -const Map swatch = { - 50: Color.fromRGBO(87, 85, 217, .1), - 100: Color.fromRGBO(87, 85, 217, .2), - 200: Color.fromRGBO(87, 85, 217, .3), - 300: Color.fromRGBO(87, 85, 217, .4), - 400: Color.fromRGBO(87, 85, 217, .5), - 500: Color.fromRGBO(87, 85, 217, .6), - 600: Color.fromRGBO(87, 85, 217, .7), - 700: Color.fromRGBO(87, 85, 217, .8), - 800: Color.fromRGBO(87, 85, 217, .9), - 900: Color.fromRGBO(87, 85, 217, 1), -}; - -const MaterialColor linkdingColor = MaterialColor(0xff5755d9, swatch); diff --git a/lib/constants/regexp.dart b/lib/constants/regexp.dart deleted file mode 100644 index dded282..0000000 --- a/lib/constants/regexp.dart +++ /dev/null @@ -1,9 +0,0 @@ -class Regexps { - static final url = - RegExp(r'/https?:\/\/(?:www\.)?([-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b)*(\/[\/\d\w\.-]*)*(?:[\?])*(.+)*/gi'); - static final urlWithoutProtocol = - RegExp(r'[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]+\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'); - static final ipAddress = RegExp(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$'); - static final domain = RegExp(r'^(([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+)$'); - static final path = RegExp(r'^\/\b([A-Za-z0-9_\-~/]*)[^\/|\.|\:]$'); -} diff --git a/lib/constants/shared_preferences_keys.dart b/lib/constants/shared_preferences_keys.dart deleted file mode 100644 index 22ba365..0000000 --- a/lib/constants/shared_preferences_keys.dart +++ /dev/null @@ -1,12 +0,0 @@ -class SharedPreferencesKeys { - static const serversInstances = "serversInstances"; - static const selectedTheme = "selectedTheme"; - static const useDynamicTheme = "useDynamicTheme"; - static const selectedColor = "selectedColor"; - static const useInAppBrowser = "useInAppBrowser"; - static const showFavicon = "showFavicon"; - static const openLinksBrowser = "openLinksBrowser"; - static const defaultTags = "defaultTags"; - static const markAsUnreadDefault = "markAsUnreadDefault"; - static const enableSlideOptions = "enableSlideOptions"; -} diff --git a/lib/constants/strings.dart b/lib/constants/strings.dart deleted file mode 100644 index c53c24c..0000000 --- a/lib/constants/strings.dart +++ /dev/null @@ -1,3 +0,0 @@ -class Strings { - static const createdBy = "JGeek00"; -} diff --git a/lib/constants/urls.dart b/lib/constants/urls.dart deleted file mode 100644 index 8605961..0000000 --- a/lib/constants/urls.dart +++ /dev/null @@ -1,11 +0,0 @@ -class Urls { - static const linkdingInstallationInstructions = - "https://github.com/sissbruecker/linkding?tab=readme-ov-file#installation"; - static const gitHubRepo = "https://github.com/JGeek00/linkdy"; - static const playStoreLink = "https://play.google.com/store/apps/details?id=com.jgeek00.linkdy&pcampaignid=web_share"; - static const linkdingRepo = "https://github.com/sissbruecker/linkding"; - static String gstatic(url) => - "https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=$url&size=16"; - static String appDetailsPage = "https://apps.jgeek00.com/8w0n3nmp891tp6q"; - static String appsWebsite = "https://apps.jgeek00.com"; -} diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart deleted file mode 100644 index 3163d31..0000000 --- a/lib/i18n/strings.g.dart +++ /dev/null @@ -1,213 +0,0 @@ -/// Generated file. Do not edit. -/// -/// Source: lib/i18n -/// To regenerate, run: `dart run slang` -/// -/// Locales: 4 -/// Strings: 848 (212 per locale) -/// -/// Built on 2026-04-28 at 08:24 UTC - -// coverage:ignore-file -// ignore_for_file: type=lint, unused_import -// dart format off - -import 'package:flutter/widgets.dart'; -import 'package:intl/intl.dart'; -import 'package:slang/generated.dart'; -import 'package:slang_flutter/slang_flutter.dart'; -export 'package:slang_flutter/slang_flutter.dart'; - -import 'strings_cs.g.dart' deferred as l_cs; -import 'strings_es.g.dart' deferred as l_es; -import 'strings_tr.g.dart' deferred as l_tr; -part 'strings_en.g.dart'; - -/// Supported locales. -/// -/// Usage: -/// - LocaleSettings.setLocale(AppLocale.en) // set locale -/// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum -/// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check -enum AppLocale with BaseAppLocale { - en(languageCode: 'en'), - cs(languageCode: 'cs'), - es(languageCode: 'es'), - tr(languageCode: 'tr'); - - const AppLocale({ - required this.languageCode, - this.scriptCode, // ignore: unused_element, unused_element_parameter - this.countryCode, // ignore: unused_element, unused_element_parameter - }); - - @override final String languageCode; - @override final String? scriptCode; - @override final String? countryCode; - - @override - Future build({ - Map? overrides, - PluralResolver? cardinalResolver, - PluralResolver? ordinalResolver, - }) async { - switch (this) { - case AppLocale.en: - return TranslationsEn( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - case AppLocale.cs: - await l_cs.loadLibrary(); - return l_cs.TranslationsCs( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - case AppLocale.es: - await l_es.loadLibrary(); - return l_es.TranslationsEs( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - case AppLocale.tr: - await l_tr.loadLibrary(); - return l_tr.TranslationsTr( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - } - } - - @override - Translations buildSync({ - Map? overrides, - PluralResolver? cardinalResolver, - PluralResolver? ordinalResolver, - }) { - switch (this) { - case AppLocale.en: - return TranslationsEn( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - case AppLocale.cs: - return l_cs.TranslationsCs( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - case AppLocale.es: - return l_es.TranslationsEs( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - case AppLocale.tr: - return l_tr.TranslationsTr( - overrides: overrides, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - } - } - - /// Gets current instance managed by [LocaleSettings]. - Translations get translations => LocaleSettings.instance.getTranslations(this); -} - -/// Method A: Simple -/// -/// No rebuild after locale change. -/// Translation happens during initialization of the widget (call of t). -/// Configurable via 'translate_var'. -/// -/// Usage: -/// String a = t.someKey.anotherKey; -/// String b = t['someKey.anotherKey']; // Only for edge cases! -Translations get t => LocaleSettings.instance.currentTranslations; - -/// Method B: Advanced -/// -/// All widgets using this method will trigger a rebuild when locale changes. -/// Use this if you have e.g. a settings page where the user can select the locale during runtime. -/// -/// Step 1: -/// wrap your App with -/// TranslationProvider( -/// child: MyApp() -/// ); -/// -/// Step 2: -/// final t = Translations.of(context); // Get t variable. -/// String a = t.someKey.anotherKey; // Use t variable. -/// String b = t['someKey.anotherKey']; // Only for edge cases! -class TranslationProvider extends BaseTranslationProvider { - TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance); - - static InheritedLocaleData of(BuildContext context) => InheritedLocaleData.of(context); -} - -/// Method B shorthand via [BuildContext] extension method. -/// Configurable via 'translate_var'. -/// -/// Usage (e.g. in a widget's build method): -/// context.t.someKey.anotherKey -extension BuildContextTranslationsExtension on BuildContext { - Translations get t => TranslationProvider.of(this).translations; -} - -/// Manages all translation instances and the current locale -class LocaleSettings extends BaseFlutterLocaleSettings { - LocaleSettings._() : super( - utils: AppLocaleUtils.instance, - lazy: true, - ); - - static final instance = LocaleSettings._(); - - // static aliases (checkout base methods for documentation) - static AppLocale get currentLocale => instance.currentLocale; - static Stream getLocaleStream() => instance.getLocaleStream(); - static Future setLocale(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocale(locale, listenToDeviceLocale: listenToDeviceLocale); - static Future setLocaleRaw(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRaw(rawLocale, listenToDeviceLocale: listenToDeviceLocale); - static Future useDeviceLocale() => instance.useDeviceLocale(); - static Future setPluralResolver({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolver( - language: language, - locale: locale, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); - - // synchronous versions - static AppLocale setLocaleSync(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocaleSync(locale, listenToDeviceLocale: listenToDeviceLocale); - static AppLocale setLocaleRawSync(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRawSync(rawLocale, listenToDeviceLocale: listenToDeviceLocale); - static AppLocale useDeviceLocaleSync() => instance.useDeviceLocaleSync(); - static void setPluralResolverSync({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolverSync( - language: language, - locale: locale, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ); -} - -/// Provides utility functions without any side effects. -class AppLocaleUtils extends BaseAppLocaleUtils { - AppLocaleUtils._() : super( - baseLocale: AppLocale.en, - locales: AppLocale.values, - ); - - static final instance = AppLocaleUtils._(); - - // static aliases (checkout base methods for documentation) - static AppLocale parse(String rawLocale) => instance.parse(rawLocale); - static AppLocale parseLocaleParts({required String languageCode, String? scriptCode, String? countryCode}) => instance.parseLocaleParts(languageCode: languageCode, scriptCode: scriptCode, countryCode: countryCode); - static AppLocale findDeviceLocale() => instance.findDeviceLocale(); - static List get supportedLocales => instance.supportedLocales; - static List get supportedLocalesRaw => instance.supportedLocalesRaw; -} diff --git a/lib/i18n/strings_cs.g.dart b/lib/i18n/strings_cs.g.dart deleted file mode 100644 index 5e3150c..0000000 --- a/lib/i18n/strings_cs.g.dart +++ /dev/null @@ -1,659 +0,0 @@ -/// -/// Generated file. Do not edit. -/// -// coverage:ignore-file -// ignore_for_file: type=lint, unused_import -// dart format off - -import 'package:flutter/widgets.dart'; -import 'package:intl/intl.dart'; -import 'package:slang/generated.dart'; -import 'strings.g.dart'; - -// Path: -class TranslationsCs with BaseTranslations implements Translations { - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - TranslationsCs({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver, TranslationMetadata? meta}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = meta ?? TranslationMetadata( - locale: AppLocale.cs, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ) { - $meta.setFlatMapFunction(_flatMapFunction); - } - - /// Metadata for the translations of . - @override final TranslationMetadata $meta; - - /// Access flat map - @override dynamic operator[](String key) => $meta.getTranslation(key); - - late final TranslationsCs _root = this; // ignore: unused_field - - @override - TranslationsCs $copyWith({TranslationMetadata? meta}) => TranslationsCs(meta: meta ?? this.$meta); - - // Translations - @override late final _TranslationsGenericCs generic = _TranslationsGenericCs._(_root); - @override late final _TranslationsOnboardingCs onboarding = _TranslationsOnboardingCs._(_root); - @override late final _TranslationsBookmarksCs bookmarks = _TranslationsBookmarksCs._(_root); - @override late final _TranslationsTagsCs tags = _TranslationsTagsCs._(_root); - @override late final _TranslationsSettingsCs settings = _TranslationsSettingsCs._(_root); - @override late final _TranslationsWebviewCs webview = _TranslationsWebviewCs._(_root); - @override late final _TranslationsColorsCs colors = _TranslationsColorsCs._(_root); -} - -// Path: generic -class _TranslationsGenericCs implements TranslationsGenericEn { - _TranslationsGenericCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get confirm => 'Potvrdit'; - @override String get cancel => 'Zrušit'; - @override String get next => 'Další'; - @override String get save => 'Uložit'; - @override String get close => 'Zavřít'; - @override String get error => 'Chyba'; - @override String get optional => 'Volitelné'; - @override String get authTokenNotValid => 'Váš autorizační token již není platný. Přihlaste se prosím znovu.'; - @override String get options => 'Možnosti'; -} - -// Path: onboarding -class _TranslationsOnboardingCs implements TranslationsOnboardingEn { - _TranslationsOnboardingCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get title => 'Vítejte v Linkdy'; - @override String get subtitle => 'Aplikace pro správu vašich záložek.'; - @override String get start => 'Začít'; - @override String get next => 'Další'; - @override String get previous => 'Předchozí'; - @override String get serverRequired => 'Vyžadován server'; - @override String get serverRequiredDescription => 'Linkdy není samostatná aplikace, ke svému chodu vyžaduje server Linkding.\nPro použití této aplikace musíte nasadit Linkding na svůj domácí server, VPS nebo jiný počítač.'; - @override String get installationInstructions => 'Pokyny k instalaci naleznete v oficiálním úložišti na GitHubu.'; - @override String get serverRunningConfirmation => 'Potvrzuji, že mám spuštěnou instanci serveru Linkding.'; - @override String get createConnection => 'Vytvořit připojení'; - @override String get createConnectionSubtitle => 'Zadejte údaje potřebné pro připojení k vašemu serveru.'; - @override String get ipAddressOrDomain => 'IP adresa nebo doména'; - @override String get port => 'Port'; - @override String get path => 'Cesta'; - @override String get invalidPath => 'Neplatná cesta'; - @override String get token => 'Token'; - @override String get required => 'Povinné'; - @override String get serverDetails => 'Podrobnosti o serveru'; - @override String get authentication => 'Autentizace'; - @override String get testConnectionUrl => 'Testovat URL připojení'; - @override String get connectionServerEstablished => 'Připojení k serveru bylo navázáno'; - @override String get testingConnection => 'Testování připojení…'; - @override String get connectionServerFailed => 'Připojení k serveru selhalo'; - @override String get connect => 'Připojit'; - @override String get connecting => 'Připojování…'; - @override String get cannotConnectToServer => 'Nelze se připojit k serveru.'; - @override String get invalidToken => 'Neplatný token.'; - @override String get invalidIpDomain => 'Neplatná IP adresa nebo doména'; - @override String get invalidPort => 'Neplatný port'; - @override String get tokenRequired => 'Token je povinný'; -} - -// Path: bookmarks -class _TranslationsBookmarksCs implements TranslationsBookmarksEn { - _TranslationsBookmarksCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get bookmarks => 'Záložky'; - @override String get noBookmarksAdded => 'Žádné záložky nebyly přidány'; - @override String get cannotLoadBookmarks => 'Záložky nelze načíst'; - @override late final _TranslationsBookmarksDatesCs dates = _TranslationsBookmarksDatesCs._(_root); - @override String get shared => 'Sdílené'; - @override String get archived => 'Archivované'; - @override String get showOnlyRead => 'Zobrazit pouze přečtené'; - @override String get showOnlyUnread => 'Zobrazit pouze nepřečtené'; - @override String get showAllBookmarks => 'Zobrazit všechny záložky'; - @override String get readStatus => 'Stav přečtení'; - @override String get all => 'Vše'; - @override String get unread => 'Nepřečtené'; - @override String get read => 'Přečtené'; - @override String get filterSort => 'Filtrování a řazení'; - @override String get sorting => 'Řazení'; - @override String get date => 'Datum'; - @override String get title => 'Název'; - @override String get ascendant => 'Vzestupně'; - @override String get descendant => 'Sestupně'; - @override late final _TranslationsBookmarksAddBookmarkCs addBookmark = _TranslationsBookmarksAddBookmarkCs._(_root); - @override late final _TranslationsBookmarksSearchCs search = _TranslationsBookmarksSearchCs._(_root); - @override late final _TranslationsBookmarksBookmarkOptionsCs bookmarkOptions = _TranslationsBookmarksBookmarkOptionsCs._(_root); - @override late final _TranslationsBookmarksShareOptionsCs shareOptions = _TranslationsBookmarksShareOptionsCs._(_root); -} - -// Path: tags -class _TranslationsTagsCs implements TranslationsTagsEn { - _TranslationsTagsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get tags => 'Štítky'; - @override String created({required Object created}) => 'Vytvořeno: ${created}'; - @override late final _TranslationsTagsCreateTagCs createTag = _TranslationsTagsCreateTagCs._(_root); - @override late final _TranslationsTagsFilteredBookmarksCs filteredBookmarks = _TranslationsTagsFilteredBookmarksCs._(_root); -} - -// Path: settings -class _TranslationsSettingsCs implements TranslationsSettingsEn { - _TranslationsSettingsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get settings => 'Nastavení'; - @override String get appSettings => 'Nastavení aplikace'; - @override String get aboutApp => 'O aplikaci'; - @override String get appVersion => 'Verze aplikace'; - @override String get createdBy => 'Vytvořil'; - @override String get visitGooglePlay => 'Navštívit Google Play'; - @override String get visitGitHubRepo => 'Navštívit GitHub repozitář'; - @override String get linkdingRepository => 'Úložiště Linkding'; - @override String get linkdingRepositoryDescription => 'Odkaz na GitHub repozitář Linkding'; - @override String get moreInfoApp => 'Více informací o aplikaci'; - @override String get moreInfoAppDescription => 'Odkaz na webové stránky aplikace'; - @override String get moreApps => 'Moje další aplikace'; - @override String get moreAppsDescription => 'Další projekty, kontakt, podpora a další'; - @override String get selectAnOption => 'Vyberte možnost'; - @override late final _TranslationsSettingsCustomizationCs customization = _TranslationsSettingsCustomizationCs._(_root); - @override late final _TranslationsSettingsGeneralSettingsCs generalSettings = _TranslationsSettingsGeneralSettingsCs._(_root); -} - -// Path: webview -class _TranslationsWebviewCs implements TranslationsWebviewEn { - _TranslationsWebviewCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get goBack => 'Zpět'; - @override String get goForward => 'Vpřed'; - @override String get reload => 'Obnovit'; - @override String get openInSystemBrowser => 'Otevřít v systémovém prohlížeči'; - @override String get copyLinkClipboard => 'Kopírovat odkaz'; - @override String get linkCopiedClipboard => 'Odkaz byl zkopírován do schránky.'; - @override String get share => 'Sdílet'; - @override String get invalidBookmarkData => 'Záložka obsahuje neplatná nebo poškozená data.'; -} - -// Path: colors -class _TranslationsColorsCs implements TranslationsColorsEn { - _TranslationsColorsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get red => 'Červená'; - @override String get green => 'Zelená'; - @override String get blue => 'Modrá'; - @override String get yellow => 'Žlutá'; - @override String get orange => 'Oranžová'; - @override String get brown => 'Hnědá'; - @override String get cyan => 'Azurová'; - @override String get purple => 'Fialová'; - @override String get pink => 'Růžová'; - @override String get deepOrange => 'Sytě oranžová'; - @override String get indigo => 'Indigová'; -} - -// Path: bookmarks.dates -class _TranslationsBookmarksDatesCs implements TranslationsBookmarksDatesEn { - _TranslationsBookmarksDatesCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String todayAt({required Object time}) => 'Dnes, ${time}'; - @override String yesterdayAt({required Object time}) => 'Včera, ${time}'; -} - -// Path: bookmarks.addBookmark -class _TranslationsBookmarksAddBookmarkCs implements TranslationsBookmarksAddBookmarkEn { - _TranslationsBookmarksAddBookmarkCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get addBookmark => 'Přidání nové záložky'; - @override String get editBookmark => 'Úprava záložky'; - @override String get bookmarkUrl => 'URL záložky'; - @override String get bookmarkDetails => 'Podrobnosti záložky'; - @override String get validateUrl => 'Ověřit URL'; - @override String get urlValid => 'Validní URL'; - @override String get urlNotValid => 'Nevalidní URL'; - @override String get cannotCheckUrl => 'URL se nepodařilo ověřit, ale přesto ji můžete uložit.'; - @override String get invalidUrl => 'Neplatná URL'; - @override String get url => 'URL'; - @override String get checkingUrl => 'Ověřování URL…'; - @override String get title => 'Název'; - @override String get description => 'Popis'; - @override String get markAsUnread => 'Označit jako nepřečtené'; - @override String get markAsUnreadDescription => 'Nepřečtené záložky lze filtrovat a po přečtení označit jako přečtené.'; - @override String get notes => 'Poznámky'; - @override String get addNotes => 'Přidat poznámky'; - @override String get tags => 'Štítky'; - @override String get noTagsAdded => 'Nepoužity žádné štítky'; - @override String get tagNoWhitespaces => 'Štítek nesmí obsahovat mezery'; - @override String get addTag => 'Přidat štítek'; - @override String get others => 'Ostatní'; - @override String get savingBookmark => 'Ukládání záložky…'; - @override String get bookmarkSavedSuccessfully => 'Záložka byla úspěšně uložena.'; - @override String get errorSavingBookmark => 'Při ukládání záložky došlo k chybě.'; - @override String get leaveEmptyUseWebsiteTitle => 'Ponechte prázdné pro automatické načtení názvu z webu.'; - @override String get leaveEmptyUseWebsiteDescription => 'Ponechte prázdné pro automatické načtení popisu z webu.'; - @override String get share => 'Sdílet'; - @override String get shareDescription => 'Sdílejte tuto záložku s ostatními registrovanými nebo anonymními uživateli.'; - @override String get urlAlreadyBookmarked => 'Tato URL již v záložkách existuje. Formulář byl předvyplněn a uložením stávající záložku aktualizujete.'; -} - -// Path: bookmarks.search -class _TranslationsBookmarksSearchCs implements TranslationsBookmarksSearchEn { - _TranslationsBookmarksSearchCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get searchBookmarks => 'Hledat záložky'; - @override String get clearSearch => 'Vymazat hledání'; - @override String get inputSearchTerm => 'Zadejte hledaný výraz'; - @override String get cannotSearchError => 'Kvůli chybě nelze vyhledávat'; - @override String get inputtedSearchTermNoResults => 'Pro zadaný výraz nebyly nalezeny žádné výsledky'; -} - -// Path: bookmarks.bookmarkOptions -class _TranslationsBookmarksBookmarkOptionsCs implements TranslationsBookmarksBookmarkOptionsEn { - _TranslationsBookmarksBookmarkOptionsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get edit => 'Upravit'; - @override String get delete => 'Smazat'; - @override String get read => 'Přečtené'; - @override String get unread => 'Nepřečtené'; - @override String get markAsUnread => 'Označit jako nepřečtené'; - @override String get markAsRead => 'Označit jako přečtené'; - @override String get shareOptions => 'Možnosti sdílení'; - @override String get shared => 'Sdílené'; - @override String get archive => 'Archivovat'; - @override String get unarchive => 'Obnovit z archivu'; - @override String get deletingBookmark => 'Mazání záložky…'; - @override String get bookmarkDeleted => 'Záložka byla smazána'; - @override String get bookmarkNotDeleted => 'Záložku se nepodařilo smazat kvůli chybě.'; - @override String get deleteBookmark => 'Smazat záložku'; - @override String get followingBookmarkDeleted => 'Tato záložka bude smazána:'; - @override String get markingAsRead => 'Označování jako přečtené…'; - @override String get markingAsUnead => 'Označování jako nepřečtené…'; - @override String get markedAsReadSuccessfully => 'Záložka byla označena jako přečtená.'; - @override String get markedAsUnreadSuccessfully => 'Záložka byla označena jako nepřečtená.'; - @override String get bookmarkNotMarkedAsRead => 'Záložku se nepodařilo označit jako přečtenou.'; - @override String get bookmarkNotMarkedAsUnread => 'Záložku se nepodařilo označit jako nepřečtenou.'; - @override String get archivingBookmark => 'Archivování záložky…'; - @override String get unarchivingBookmark => 'Obnovování záložky z archivu…'; - @override String get bookmarkArchivedSuccessfully => 'Záložka byla archivována.'; - @override String get bookmarkUnrchivedSuccessfully => 'Záložka byla úspěšně obnovena z archivu.'; - @override String get bookmarkNotArchived => 'Záložku se nepodařilo archivovat.'; - @override String get bookmarkNotUnrchived => 'Záložku se nepodařilo obnovit z archivu.'; - @override String get shareThirdPartyApp => 'Sdílet pomocí externí aplikace'; - @override String get shareInternally => 'Sdílet interně'; - @override String get unshareInternally => 'Zrušit interní sdílení'; -} - -// Path: bookmarks.shareOptions -class _TranslationsBookmarksShareOptionsCs implements TranslationsBookmarksShareOptionsEn { - _TranslationsBookmarksShareOptionsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get shareOptions => 'Možnosti sdílení'; - @override String get shareInternally => 'Sdílet interně'; - @override String get unshareInternally => 'Zrušit interní sdílení'; - @override String get shareInternallyDescription => 'Sdílet interně s ostatními uživateli této instance Linkding'; - @override String get unshareInternallyDescription => 'Zrušit interní sdílení této záložky'; - @override String get shareExternally => 'Sdílet URL záložky externě'; - @override String get shareExternallyDescription => 'Sdílet URL pomocí externí aplikace v systému'; - @override String get sharingBookmark => 'Sdílení záložky…'; - @override String get unsharingBookmark => 'Rušení sdílení záložky…'; - @override String get bookmarkSharedSuccessfully => 'Záložka je nyní sdílena.'; - @override String get bookmarkNotShared => 'Záložku se nepodařilo sdílet.'; - @override String get bookmarkUnsharedSuccessfully => 'Interní sdílení bylo zrušeno.'; - @override String get bookmarkNotUnshared => 'Sdílení se nepodařilo zrušit.'; -} - -// Path: tags.createTag -class _TranslationsTagsCreateTagCs implements TranslationsTagsCreateTagEn { - _TranslationsTagsCreateTagCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get createTag => 'Vytvořit štítek'; - @override String get name => 'Název'; - @override String get creatingTag => 'Vytváření štítku…'; - @override String get errorCreatingTag => 'Při vytváření štítku došlo k chybě.'; -} - -// Path: tags.filteredBookmarks -class _TranslationsTagsFilteredBookmarksCs implements TranslationsTagsFilteredBookmarksEn { - _TranslationsTagsFilteredBookmarksCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get noBookmarksWithThisTag => 'Žádné záložky s tímto štítkem'; - @override String get noArchivedBookmarks => 'Žádné archivované záložky'; - @override String get noSharedBookmarks => 'Žádné sdílené záložky'; -} - -// Path: settings.customization -class _TranslationsSettingsCustomizationCs implements TranslationsSettingsCustomizationEn { - _TranslationsSettingsCustomizationCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get customization => 'Přizpůsobení'; - @override String get customizationDescription => 'Nastavte motiv aplikace a barevnou paletu.'; - @override String get theme => 'Motiv'; - @override String get light => 'Světlý'; - @override String get dark => 'Tmavý'; - @override String get systemDefined => 'Dle systému'; - @override String get color => 'Barva'; - @override String get useDynamicTheme => 'Použít dynamický motiv'; -} - -// Path: settings.generalSettings -class _TranslationsSettingsGeneralSettingsCs implements TranslationsSettingsGeneralSettingsEn { - _TranslationsSettingsGeneralSettingsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get generalSettings => 'Obecná nastavení'; - @override String get generalSettingsDescription => 'Obecná vylepšení pro aplikaci.'; - @override String get bookmarks => 'Záložky'; - @override String get showFavicon => 'Zobrazit ikony (favicon)'; - @override String get showFaviconDescription => 'Zobrazit ikonu webu u každé záložky.'; - @override String get disconnectFromServer => 'Odpojit od serveru'; - @override late final _TranslationsSettingsGeneralSettingsDisconnectModalCs disconnectModal = _TranslationsSettingsGeneralSettingsDisconnectModalCs._(_root); - @override String get useInAppBrowser => 'Použít integrovaný prohlížeč'; - @override String get useInAppBrowserDescription => 'Otevírá záložky v aplikaci místo v systémovém prohlížeči. V režimu tabletu je tento prohlížeč používán vždy.'; - @override String get openLinksWith => 'Otevírat odkazy pomocí…'; - @override String get internalBrowser => 'Integrovaný prohlížeč aplikace'; - @override String get browserCustomTab => 'Vlastní karta prohlížeče'; - @override String get systemBrowser => 'Systémový prohlížeč'; - @override String get tags => 'Štítky'; - @override late final _TranslationsSettingsGeneralSettingsDefaultTagsCs defaultTags = _TranslationsSettingsGeneralSettingsDefaultTagsCs._(_root); - @override String get others => 'Ostatní'; - @override String get setMarkAsUnreadDefault => 'Označit vždy jako nepřečtené'; - @override String get setMarkAsUnreadDefaultDescription => 'Při vytváření nové záložky bude automaticky přednastavena možnost „Označit jako nepřečtené“.'; - @override String get enableSlideOptions => 'Povolit gesta posouvání'; - @override String get enableSlideOptionsDescription => 'Povolit akce posunutím prstu v seznamu záložek'; -} - -// Path: settings.generalSettings.disconnectModal -class _TranslationsSettingsGeneralSettingsDisconnectModalCs implements TranslationsSettingsGeneralSettingsDisconnectModalEn { - _TranslationsSettingsGeneralSettingsDisconnectModalCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get title => 'Odpojit se?'; - @override String get description => 'Opravdu se chcete odpojit od serveru?\nBudete přesměrováni na úvodní nastavení.'; -} - -// Path: settings.generalSettings.defaultTags -class _TranslationsSettingsGeneralSettingsDefaultTagsCs implements TranslationsSettingsGeneralSettingsDefaultTagsEn { - _TranslationsSettingsGeneralSettingsDefaultTagsCs._(this._root); - - final TranslationsCs _root; // ignore: unused_field - - // Translations - @override String get defaultTags => 'Výchozí štítky'; - @override String get defaultTagsDescription => 'Definujte seznam štítků, které budou automaticky přidány k nové záložce'; - @override String get newTag => 'Nový štítek'; - @override String get addTag => 'Přidat štítek'; - @override String get removeThisTag => 'Odebrat tento štítek'; - @override String get noDefaultTags => 'Nejsou nastaveny žádné výchozí štítky'; -} - -/// The flat map containing all translations for locale . -/// Only for edge cases! For simple maps, use the map function of this library. -/// -/// The Dart AOT compiler has issues with very large switch statements, -/// so the map is split into smaller functions (512 entries each). -extension on TranslationsCs { - dynamic _flatMapFunction(String path) { - return switch (path) { - 'generic.confirm' => 'Potvrdit', - 'generic.cancel' => 'Zrušit', - 'generic.next' => 'Další', - 'generic.save' => 'Uložit', - 'generic.close' => 'Zavřít', - 'generic.error' => 'Chyba', - 'generic.optional' => 'Volitelné', - 'generic.authTokenNotValid' => 'Váš autorizační token již není platný. Přihlaste se prosím znovu.', - 'generic.options' => 'Možnosti', - 'onboarding.title' => 'Vítejte v Linkdy', - 'onboarding.subtitle' => 'Aplikace pro správu vašich záložek.', - 'onboarding.start' => 'Začít', - 'onboarding.next' => 'Další', - 'onboarding.previous' => 'Předchozí', - 'onboarding.serverRequired' => 'Vyžadován server', - 'onboarding.serverRequiredDescription' => 'Linkdy není samostatná aplikace, ke svému chodu vyžaduje server Linkding.\nPro použití této aplikace musíte nasadit Linkding na svůj domácí server, VPS nebo jiný počítač.', - 'onboarding.installationInstructions' => 'Pokyny k instalaci naleznete v oficiálním úložišti na GitHubu.', - 'onboarding.serverRunningConfirmation' => 'Potvrzuji, že mám spuštěnou instanci serveru Linkding.', - 'onboarding.createConnection' => 'Vytvořit připojení', - 'onboarding.createConnectionSubtitle' => 'Zadejte údaje potřebné pro připojení k vašemu serveru.', - 'onboarding.ipAddressOrDomain' => 'IP adresa nebo doména', - 'onboarding.port' => 'Port', - 'onboarding.path' => 'Cesta', - 'onboarding.invalidPath' => 'Neplatná cesta', - 'onboarding.token' => 'Token', - 'onboarding.required' => 'Povinné', - 'onboarding.serverDetails' => 'Podrobnosti o serveru', - 'onboarding.authentication' => 'Autentizace', - 'onboarding.testConnectionUrl' => 'Testovat URL připojení', - 'onboarding.connectionServerEstablished' => 'Připojení k serveru bylo navázáno', - 'onboarding.testingConnection' => 'Testování připojení…', - 'onboarding.connectionServerFailed' => 'Připojení k serveru selhalo', - 'onboarding.connect' => 'Připojit', - 'onboarding.connecting' => 'Připojování…', - 'onboarding.cannotConnectToServer' => 'Nelze se připojit k serveru.', - 'onboarding.invalidToken' => 'Neplatný token.', - 'onboarding.invalidIpDomain' => 'Neplatná IP adresa nebo doména', - 'onboarding.invalidPort' => 'Neplatný port', - 'onboarding.tokenRequired' => 'Token je povinný', - 'bookmarks.bookmarks' => 'Záložky', - 'bookmarks.noBookmarksAdded' => 'Žádné záložky nebyly přidány', - 'bookmarks.cannotLoadBookmarks' => 'Záložky nelze načíst', - 'bookmarks.dates.todayAt' => ({required Object time}) => 'Dnes, ${time}', - 'bookmarks.dates.yesterdayAt' => ({required Object time}) => 'Včera, ${time}', - 'bookmarks.shared' => 'Sdílené', - 'bookmarks.archived' => 'Archivované', - 'bookmarks.showOnlyRead' => 'Zobrazit pouze přečtené', - 'bookmarks.showOnlyUnread' => 'Zobrazit pouze nepřečtené', - 'bookmarks.showAllBookmarks' => 'Zobrazit všechny záložky', - 'bookmarks.readStatus' => 'Stav přečtení', - 'bookmarks.all' => 'Vše', - 'bookmarks.unread' => 'Nepřečtené', - 'bookmarks.read' => 'Přečtené', - 'bookmarks.filterSort' => 'Filtrování a řazení', - 'bookmarks.sorting' => 'Řazení', - 'bookmarks.date' => 'Datum', - 'bookmarks.title' => 'Název', - 'bookmarks.ascendant' => 'Vzestupně', - 'bookmarks.descendant' => 'Sestupně', - 'bookmarks.addBookmark.addBookmark' => 'Přidání nové záložky', - 'bookmarks.addBookmark.editBookmark' => 'Úprava záložky', - 'bookmarks.addBookmark.bookmarkUrl' => 'URL záložky', - 'bookmarks.addBookmark.bookmarkDetails' => 'Podrobnosti záložky', - 'bookmarks.addBookmark.validateUrl' => 'Ověřit URL', - 'bookmarks.addBookmark.urlValid' => 'Validní URL', - 'bookmarks.addBookmark.urlNotValid' => 'Nevalidní URL', - 'bookmarks.addBookmark.cannotCheckUrl' => 'URL se nepodařilo ověřit, ale přesto ji můžete uložit.', - 'bookmarks.addBookmark.invalidUrl' => 'Neplatná URL', - 'bookmarks.addBookmark.url' => 'URL', - 'bookmarks.addBookmark.checkingUrl' => 'Ověřování URL…', - 'bookmarks.addBookmark.title' => 'Název', - 'bookmarks.addBookmark.description' => 'Popis', - 'bookmarks.addBookmark.markAsUnread' => 'Označit jako nepřečtené', - 'bookmarks.addBookmark.markAsUnreadDescription' => 'Nepřečtené záložky lze filtrovat a po přečtení označit jako přečtené.', - 'bookmarks.addBookmark.notes' => 'Poznámky', - 'bookmarks.addBookmark.addNotes' => 'Přidat poznámky', - 'bookmarks.addBookmark.tags' => 'Štítky', - 'bookmarks.addBookmark.noTagsAdded' => 'Nepoužity žádné štítky', - 'bookmarks.addBookmark.tagNoWhitespaces' => 'Štítek nesmí obsahovat mezery', - 'bookmarks.addBookmark.addTag' => 'Přidat štítek', - 'bookmarks.addBookmark.others' => 'Ostatní', - 'bookmarks.addBookmark.savingBookmark' => 'Ukládání záložky…', - 'bookmarks.addBookmark.bookmarkSavedSuccessfully' => 'Záložka byla úspěšně uložena.', - 'bookmarks.addBookmark.errorSavingBookmark' => 'Při ukládání záložky došlo k chybě.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteTitle' => 'Ponechte prázdné pro automatické načtení názvu z webu.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteDescription' => 'Ponechte prázdné pro automatické načtení popisu z webu.', - 'bookmarks.addBookmark.share' => 'Sdílet', - 'bookmarks.addBookmark.shareDescription' => 'Sdílejte tuto záložku s ostatními registrovanými nebo anonymními uživateli.', - 'bookmarks.addBookmark.urlAlreadyBookmarked' => 'Tato URL již v záložkách existuje. Formulář byl předvyplněn a uložením stávající záložku aktualizujete.', - 'bookmarks.search.searchBookmarks' => 'Hledat záložky', - 'bookmarks.search.clearSearch' => 'Vymazat hledání', - 'bookmarks.search.inputSearchTerm' => 'Zadejte hledaný výraz', - 'bookmarks.search.cannotSearchError' => 'Kvůli chybě nelze vyhledávat', - 'bookmarks.search.inputtedSearchTermNoResults' => 'Pro zadaný výraz nebyly nalezeny žádné výsledky', - 'bookmarks.bookmarkOptions.edit' => 'Upravit', - 'bookmarks.bookmarkOptions.delete' => 'Smazat', - 'bookmarks.bookmarkOptions.read' => 'Přečtené', - 'bookmarks.bookmarkOptions.unread' => 'Nepřečtené', - 'bookmarks.bookmarkOptions.markAsUnread' => 'Označit jako nepřečtené', - 'bookmarks.bookmarkOptions.markAsRead' => 'Označit jako přečtené', - 'bookmarks.bookmarkOptions.shareOptions' => 'Možnosti sdílení', - 'bookmarks.bookmarkOptions.shared' => 'Sdílené', - 'bookmarks.bookmarkOptions.archive' => 'Archivovat', - 'bookmarks.bookmarkOptions.unarchive' => 'Obnovit z archivu', - 'bookmarks.bookmarkOptions.deletingBookmark' => 'Mazání záložky…', - 'bookmarks.bookmarkOptions.bookmarkDeleted' => 'Záložka byla smazána', - 'bookmarks.bookmarkOptions.bookmarkNotDeleted' => 'Záložku se nepodařilo smazat kvůli chybě.', - 'bookmarks.bookmarkOptions.deleteBookmark' => 'Smazat záložku', - 'bookmarks.bookmarkOptions.followingBookmarkDeleted' => 'Tato záložka bude smazána:', - 'bookmarks.bookmarkOptions.markingAsRead' => 'Označování jako přečtené…', - 'bookmarks.bookmarkOptions.markingAsUnead' => 'Označování jako nepřečtené…', - 'bookmarks.bookmarkOptions.markedAsReadSuccessfully' => 'Záložka byla označena jako přečtená.', - 'bookmarks.bookmarkOptions.markedAsUnreadSuccessfully' => 'Záložka byla označena jako nepřečtená.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead' => 'Záložku se nepodařilo označit jako přečtenou.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread' => 'Záložku se nepodařilo označit jako nepřečtenou.', - 'bookmarks.bookmarkOptions.archivingBookmark' => 'Archivování záložky…', - 'bookmarks.bookmarkOptions.unarchivingBookmark' => 'Obnovování záložky z archivu…', - 'bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully' => 'Záložka byla archivována.', - 'bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully' => 'Záložka byla úspěšně obnovena z archivu.', - 'bookmarks.bookmarkOptions.bookmarkNotArchived' => 'Záložku se nepodařilo archivovat.', - 'bookmarks.bookmarkOptions.bookmarkNotUnrchived' => 'Záložku se nepodařilo obnovit z archivu.', - 'bookmarks.bookmarkOptions.shareThirdPartyApp' => 'Sdílet pomocí externí aplikace', - 'bookmarks.bookmarkOptions.shareInternally' => 'Sdílet interně', - 'bookmarks.bookmarkOptions.unshareInternally' => 'Zrušit interní sdílení', - 'bookmarks.shareOptions.shareOptions' => 'Možnosti sdílení', - 'bookmarks.shareOptions.shareInternally' => 'Sdílet interně', - 'bookmarks.shareOptions.unshareInternally' => 'Zrušit interní sdílení', - 'bookmarks.shareOptions.shareInternallyDescription' => 'Sdílet interně s ostatními uživateli této instance Linkding', - 'bookmarks.shareOptions.unshareInternallyDescription' => 'Zrušit interní sdílení této záložky', - 'bookmarks.shareOptions.shareExternally' => 'Sdílet URL záložky externě', - 'bookmarks.shareOptions.shareExternallyDescription' => 'Sdílet URL pomocí externí aplikace v systému', - 'bookmarks.shareOptions.sharingBookmark' => 'Sdílení záložky…', - 'bookmarks.shareOptions.unsharingBookmark' => 'Rušení sdílení záložky…', - 'bookmarks.shareOptions.bookmarkSharedSuccessfully' => 'Záložka je nyní sdílena.', - 'bookmarks.shareOptions.bookmarkNotShared' => 'Záložku se nepodařilo sdílet.', - 'bookmarks.shareOptions.bookmarkUnsharedSuccessfully' => 'Interní sdílení bylo zrušeno.', - 'bookmarks.shareOptions.bookmarkNotUnshared' => 'Sdílení se nepodařilo zrušit.', - 'tags.tags' => 'Štítky', - 'tags.created' => ({required Object created}) => 'Vytvořeno: ${created}', - 'tags.createTag.createTag' => 'Vytvořit štítek', - 'tags.createTag.name' => 'Název', - 'tags.createTag.creatingTag' => 'Vytváření štítku…', - 'tags.createTag.errorCreatingTag' => 'Při vytváření štítku došlo k chybě.', - 'tags.filteredBookmarks.noBookmarksWithThisTag' => 'Žádné záložky s tímto štítkem', - 'tags.filteredBookmarks.noArchivedBookmarks' => 'Žádné archivované záložky', - 'tags.filteredBookmarks.noSharedBookmarks' => 'Žádné sdílené záložky', - 'settings.settings' => 'Nastavení', - 'settings.appSettings' => 'Nastavení aplikace', - 'settings.aboutApp' => 'O aplikaci', - 'settings.appVersion' => 'Verze aplikace', - 'settings.createdBy' => 'Vytvořil', - 'settings.visitGooglePlay' => 'Navštívit Google Play', - 'settings.visitGitHubRepo' => 'Navštívit GitHub repozitář', - 'settings.linkdingRepository' => 'Úložiště Linkding', - 'settings.linkdingRepositoryDescription' => 'Odkaz na GitHub repozitář Linkding', - 'settings.moreInfoApp' => 'Více informací o aplikaci', - 'settings.moreInfoAppDescription' => 'Odkaz na webové stránky aplikace', - 'settings.moreApps' => 'Moje další aplikace', - 'settings.moreAppsDescription' => 'Další projekty, kontakt, podpora a další', - 'settings.selectAnOption' => 'Vyberte možnost', - 'settings.customization.customization' => 'Přizpůsobení', - 'settings.customization.customizationDescription' => 'Nastavte motiv aplikace a barevnou paletu.', - 'settings.customization.theme' => 'Motiv', - 'settings.customization.light' => 'Světlý', - 'settings.customization.dark' => 'Tmavý', - 'settings.customization.systemDefined' => 'Dle systému', - 'settings.customization.color' => 'Barva', - 'settings.customization.useDynamicTheme' => 'Použít dynamický motiv', - 'settings.generalSettings.generalSettings' => 'Obecná nastavení', - 'settings.generalSettings.generalSettingsDescription' => 'Obecná vylepšení pro aplikaci.', - 'settings.generalSettings.bookmarks' => 'Záložky', - 'settings.generalSettings.showFavicon' => 'Zobrazit ikony (favicon)', - 'settings.generalSettings.showFaviconDescription' => 'Zobrazit ikonu webu u každé záložky.', - 'settings.generalSettings.disconnectFromServer' => 'Odpojit od serveru', - 'settings.generalSettings.disconnectModal.title' => 'Odpojit se?', - 'settings.generalSettings.disconnectModal.description' => 'Opravdu se chcete odpojit od serveru?\nBudete přesměrováni na úvodní nastavení.', - 'settings.generalSettings.useInAppBrowser' => 'Použít integrovaný prohlížeč', - 'settings.generalSettings.useInAppBrowserDescription' => 'Otevírá záložky v aplikaci místo v systémovém prohlížeči. V režimu tabletu je tento prohlížeč používán vždy.', - 'settings.generalSettings.openLinksWith' => 'Otevírat odkazy pomocí…', - 'settings.generalSettings.internalBrowser' => 'Integrovaný prohlížeč aplikace', - 'settings.generalSettings.browserCustomTab' => 'Vlastní karta prohlížeče', - 'settings.generalSettings.systemBrowser' => 'Systémový prohlížeč', - 'settings.generalSettings.tags' => 'Štítky', - 'settings.generalSettings.defaultTags.defaultTags' => 'Výchozí štítky', - 'settings.generalSettings.defaultTags.defaultTagsDescription' => 'Definujte seznam štítků, které budou automaticky přidány k nové záložce', - 'settings.generalSettings.defaultTags.newTag' => 'Nový štítek', - 'settings.generalSettings.defaultTags.addTag' => 'Přidat štítek', - 'settings.generalSettings.defaultTags.removeThisTag' => 'Odebrat tento štítek', - 'settings.generalSettings.defaultTags.noDefaultTags' => 'Nejsou nastaveny žádné výchozí štítky', - 'settings.generalSettings.others' => 'Ostatní', - 'settings.generalSettings.setMarkAsUnreadDefault' => 'Označit vždy jako nepřečtené', - 'settings.generalSettings.setMarkAsUnreadDefaultDescription' => 'Při vytváření nové záložky bude automaticky přednastavena možnost „Označit jako nepřečtené“.', - 'settings.generalSettings.enableSlideOptions' => 'Povolit gesta posouvání', - 'settings.generalSettings.enableSlideOptionsDescription' => 'Povolit akce posunutím prstu v seznamu záložek', - 'webview.goBack' => 'Zpět', - 'webview.goForward' => 'Vpřed', - 'webview.reload' => 'Obnovit', - 'webview.openInSystemBrowser' => 'Otevřít v systémovém prohlížeči', - 'webview.copyLinkClipboard' => 'Kopírovat odkaz', - 'webview.linkCopiedClipboard' => 'Odkaz byl zkopírován do schránky.', - 'webview.share' => 'Sdílet', - 'webview.invalidBookmarkData' => 'Záložka obsahuje neplatná nebo poškozená data.', - 'colors.red' => 'Červená', - 'colors.green' => 'Zelená', - 'colors.blue' => 'Modrá', - 'colors.yellow' => 'Žlutá', - 'colors.orange' => 'Oranžová', - 'colors.brown' => 'Hnědá', - 'colors.cyan' => 'Azurová', - 'colors.purple' => 'Fialová', - 'colors.pink' => 'Růžová', - 'colors.deepOrange' => 'Sytě oranžová', - 'colors.indigo' => 'Indigová', - _ => null, - }; - } -} diff --git a/lib/i18n/strings_cs.i18n.json b/lib/i18n/strings_cs.i18n.json deleted file mode 100644 index dae683d..0000000 --- a/lib/i18n/strings_cs.i18n.json +++ /dev/null @@ -1,251 +0,0 @@ -{ - "generic": { - "confirm": "Potvrdit", - "cancel": "Zrušit", - "next": "Další", - "save": "Uložit", - "close": "Zavřít", - "error": "Chyba", - "optional": "Volitelné", - "authTokenNotValid": "Váš autorizační token již není platný. Přihlaste se prosím znovu.", - "options": "Možnosti" - }, - "onboarding": { - "title": "Vítejte v Linkdy", - "subtitle": "Aplikace pro správu vašich záložek.", - "start": "Začít", - "next": "Další", - "previous": "Předchozí", - "serverRequired": "Vyžadován server", - "serverRequiredDescription": "Linkdy není samostatná aplikace, ke svému chodu vyžaduje server Linkding.\nPro použití této aplikace musíte nasadit Linkding na svůj domácí server, VPS nebo jiný počítač.", - "installationInstructions": "Pokyny k instalaci naleznete v oficiálním úložišti na GitHubu.", - "serverRunningConfirmation": "Potvrzuji, že mám spuštěnou instanci serveru Linkding.", - "createConnection": "Vytvořit připojení", - "createConnectionSubtitle": "Zadejte údaje potřebné pro připojení k vašemu serveru.", - "ipAddressOrDomain": "IP adresa nebo doména", - "port": "Port", - "path": "Cesta", - "invalidPath": "Neplatná cesta", - "token": "Token", - "required": "Povinné", - "serverDetails": "Podrobnosti o serveru", - "authentication": "Autentizace", - "testConnectionUrl": "Testovat URL připojení", - "connectionServerEstablished": "Připojení k serveru bylo navázáno", - "testingConnection": "Testování připojení…", - "connectionServerFailed": "Připojení k serveru selhalo", - "connect": "Připojit", - "connecting": "Připojování…", - "cannotConnectToServer": "Nelze se připojit k serveru.", - "invalidToken": "Neplatný token.", - "invalidIpDomain": "Neplatná IP adresa nebo doména", - "invalidPort": "Neplatný port", - "tokenRequired": "Token je povinný" - }, - "bookmarks": { - "bookmarks": "Záložky", - "noBookmarksAdded": "Žádné záložky nebyly přidány", - "cannotLoadBookmarks": "Záložky nelze načíst", - "dates": { - "todayAt": "Dnes, $time", - "yesterdayAt": "Včera, $time" - }, - "shared": "Sdílené", - "archived": "Archivované", - "showOnlyRead": "Zobrazit pouze přečtené", - "showOnlyUnread": "Zobrazit pouze nepřečtené", - "showAllBookmarks": "Zobrazit všechny záložky", - "readStatus": "Stav přečtení", - "all": "Vše", - "unread": "Nepřečtené", - "read": "Přečtené", - "filterSort": "Filtrování a řazení", - "sorting": "Řazení", - "date": "Datum", - "title": "Název", - "ascendant": "Vzestupně", - "descendant": "Sestupně", - "addBookmark": { - "addBookmark": "Přidání nové záložky", - "editBookmark": "Úprava záložky", - "bookmarkUrl": "URL záložky", - "bookmarkDetails": "Podrobnosti záložky", - "validateUrl": "Ověřit URL", - "urlValid": "Validní URL", - "urlNotValid": "Nevalidní URL", - "cannotCheckUrl": "URL se nepodařilo ověřit, ale přesto ji můžete uložit.", - "invalidUrl": "Neplatná URL", - "url": "URL", - "checkingUrl": "Ověřování URL…", - "title": "Název", - "description": "Popis", - "markAsUnread": "Označit jako nepřečtené", - "markAsUnreadDescription": "Nepřečtené záložky lze filtrovat a po přečtení označit jako přečtené.", - "notes": "Poznámky", - "addNotes": "Přidat poznámky", - "tags": "Štítky", - "noTagsAdded": "Nepoužity žádné štítky", - "tagNoWhitespaces": "Štítek nesmí obsahovat mezery", - "addTag": "Přidat štítek", - "others": "Ostatní", - "savingBookmark": "Ukládání záložky…", - "bookmarkSavedSuccessfully": "Záložka byla úspěšně uložena.", - "errorSavingBookmark": "Při ukládání záložky došlo k chybě.", - "leaveEmptyUseWebsiteTitle": "Ponechte prázdné pro automatické načtení názvu z webu.", - "leaveEmptyUseWebsiteDescription": "Ponechte prázdné pro automatické načtení popisu z webu.", - "share": "Sdílet", - "shareDescription": "Sdílejte tuto záložku s ostatními registrovanými nebo anonymními uživateli.", - "urlAlreadyBookmarked": "Tato URL již v záložkách existuje. Formulář byl předvyplněn a uložením stávající záložku aktualizujete." - }, - "search": { - "searchBookmarks": "Hledat záložky", - "clearSearch": "Vymazat hledání", - "inputSearchTerm": "Zadejte hledaný výraz", - "cannotSearchError": "Kvůli chybě nelze vyhledávat", - "inputtedSearchTermNoResults": "Pro zadaný výraz nebyly nalezeny žádné výsledky" - }, - "bookmarkOptions": { - "edit": "Upravit", - "delete": "Smazat", - "read": "Přečtené", - "unread": "Nepřečtené", - "markAsUnread": "Označit jako nepřečtené", - "markAsRead": "Označit jako přečtené", - "shareOptions": "Možnosti sdílení", - "shared": "Sdílené", - "archive": "Archivovat", - "unarchive": "Obnovit z archivu", - "deletingBookmark": "Mazání záložky…", - "bookmarkDeleted": "Záložka byla smazána", - "bookmarkNotDeleted": "Záložku se nepodařilo smazat kvůli chybě.", - "deleteBookmark": "Smazat záložku", - "followingBookmarkDeleted": "Tato záložka bude smazána:", - "markingAsRead": "Označování jako přečtené…", - "markingAsUnead": "Označování jako nepřečtené…", - "markedAsReadSuccessfully": "Záložka byla označena jako přečtená.", - "markedAsUnreadSuccessfully": "Záložka byla označena jako nepřečtená.", - "bookmarkNotMarkedAsRead": "Záložku se nepodařilo označit jako přečtenou.", - "bookmarkNotMarkedAsUnread": "Záložku se nepodařilo označit jako nepřečtenou.", - "archivingBookmark": "Archivování záložky…", - "unarchivingBookmark": "Obnovování záložky z archivu…", - "bookmarkArchivedSuccessfully": "Záložka byla archivována.", - "bookmarkUnrchivedSuccessfully": "Záložka byla úspěšně obnovena z archivu.", - "bookmarkNotArchived": "Záložku se nepodařilo archivovat.", - "bookmarkNotUnrchived": "Záložku se nepodařilo obnovit z archivu.", - "shareThirdPartyApp": "Sdílet pomocí externí aplikace", - "shareInternally": "Sdílet interně", - "unshareInternally": "Zrušit interní sdílení" - }, - "shareOptions": { - "shareOptions": "Možnosti sdílení", - "shareInternally": "Sdílet interně", - "unshareInternally": "Zrušit interní sdílení", - "shareInternallyDescription": "Sdílet interně s ostatními uživateli této instance Linkding", - "unshareInternallyDescription": "Zrušit interní sdílení této záložky", - "shareExternally": "Sdílet URL záložky externě", - "shareExternallyDescription": "Sdílet URL pomocí externí aplikace v systému", - "sharingBookmark": "Sdílení záložky…", - "unsharingBookmark": "Rušení sdílení záložky…", - "bookmarkSharedSuccessfully": "Záložka je nyní sdílena.", - "bookmarkNotShared": "Záložku se nepodařilo sdílet.", - "bookmarkUnsharedSuccessfully": "Interní sdílení bylo zrušeno.", - "bookmarkNotUnshared": "Sdílení se nepodařilo zrušit." - } - }, - "tags": { - "tags": "Štítky", - "created": "Vytvořeno: $created", - "createTag": { - "createTag": "Vytvořit štítek", - "name": "Název", - "creatingTag": "Vytváření štítku…", - "errorCreatingTag": "Při vytváření štítku došlo k chybě." - }, - "filteredBookmarks": { - "noBookmarksWithThisTag": "Žádné záložky s tímto štítkem", - "noArchivedBookmarks": "Žádné archivované záložky", - "noSharedBookmarks": "Žádné sdílené záložky" - } - }, - "settings": { - "settings": "Nastavení", - "appSettings": "Nastavení aplikace", - "aboutApp": "O aplikaci", - "appVersion": "Verze aplikace", - "createdBy": "Vytvořil", - "visitGooglePlay": "Navštívit Google Play", - "visitGitHubRepo": "Navštívit GitHub repozitář", - "linkdingRepository": "Úložiště Linkding", - "linkdingRepositoryDescription": "Odkaz na GitHub repozitář Linkding", - "moreInfoApp": "Více informací o aplikaci", - "moreInfoAppDescription": "Odkaz na webové stránky aplikace", - "moreApps": "Moje další aplikace", - "moreAppsDescription": "Další projekty, kontakt, podpora a další", - "selectAnOption": "Vyberte možnost", - "customization": { - "customization": "Přizpůsobení", - "customizationDescription": "Nastavte motiv aplikace a barevnou paletu.", - "theme": "Motiv", - "light": "Světlý", - "dark": "Tmavý", - "systemDefined": "Dle systému", - "color": "Barva", - "useDynamicTheme": "Použít dynamický motiv" - }, - "generalSettings": { - "generalSettings": "Obecná nastavení", - "generalSettingsDescription": "Obecná vylepšení pro aplikaci.", - "bookmarks": "Záložky", - "showFavicon": "Zobrazit ikony (favicon)", - "showFaviconDescription": "Zobrazit ikonu webu u každé záložky.", - "disconnectFromServer": "Odpojit od serveru", - "disconnectModal": { - "title": "Odpojit se?", - "description": "Opravdu se chcete odpojit od serveru?\nBudete přesměrováni na úvodní nastavení." - }, - "useInAppBrowser": "Použít integrovaný prohlížeč", - "useInAppBrowserDescription": "Otevírá záložky v aplikaci místo v systémovém prohlížeči. V režimu tabletu je tento prohlížeč používán vždy.", - "openLinksWith": "Otevírat odkazy pomocí…", - "internalBrowser": "Integrovaný prohlížeč aplikace", - "browserCustomTab": "Vlastní karta prohlížeče", - "systemBrowser": "Systémový prohlížeč", - "tags": "Štítky", - "defaultTags": { - "defaultTags": "Výchozí štítky", - "defaultTagsDescription": "Definujte seznam štítků, které budou automaticky přidány k nové záložce", - "newTag": "Nový štítek", - "addTag": "Přidat štítek", - "removeThisTag": "Odebrat tento štítek", - "noDefaultTags": "Nejsou nastaveny žádné výchozí štítky" - }, - "others": "Ostatní", - "setMarkAsUnreadDefault": "Označit vždy jako nepřečtené", - "setMarkAsUnreadDefaultDescription": "Při vytváření nové záložky bude automaticky přednastavena možnost „Označit jako nepřečtené“.", - "enableSlideOptions": "Povolit gesta posouvání", - "enableSlideOptionsDescription": "Povolit akce posunutím prstu v seznamu záložek" - } - }, - "webview": { - "goBack": "Zpět", - "goForward": "Vpřed", - "reload": "Obnovit", - "openInSystemBrowser": "Otevřít v systémovém prohlížeči", - "copyLinkClipboard": "Kopírovat odkaz", - "linkCopiedClipboard": "Odkaz byl zkopírován do schránky.", - "share": "Sdílet", - "invalidBookmarkData": "Záložka obsahuje neplatná nebo poškozená data." - }, - "colors": { - "red": "Červená", - "green": "Zelená", - "blue": "Modrá", - "yellow": "Žlutá", - "orange": "Oranžová", - "brown": "Hnědá", - "cyan": "Azurová", - "purple": "Fialová", - "pink": "Růžová", - "deepOrange": "Sytě oranžová", - "indigo": "Indigová" - } -} diff --git a/lib/i18n/strings_en.g.dart b/lib/i18n/strings_en.g.dart deleted file mode 100644 index 459ae42..0000000 --- a/lib/i18n/strings_en.g.dart +++ /dev/null @@ -1,1094 +0,0 @@ -/// -/// Generated file. Do not edit. -/// -// coverage:ignore-file -// ignore_for_file: type=lint, unused_import -// dart format off - -part of 'strings.g.dart'; - -// Path: -typedef TranslationsEn = Translations; // ignore: unused_element -class Translations with BaseTranslations { - /// Returns the current translations of the given [context]. - /// - /// Usage: - /// final t = Translations.of(context); - static Translations of(BuildContext context) => InheritedLocaleData.of(context).translations; - - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - Translations({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver, TranslationMetadata? meta}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = meta ?? TranslationMetadata( - locale: AppLocale.en, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ) { - $meta.setFlatMapFunction(_flatMapFunction); - } - - /// Metadata for the translations of . - @override final TranslationMetadata $meta; - - /// Access flat map - dynamic operator[](String key) => $meta.getTranslation(key); - - late final Translations _root = this; // ignore: unused_field - - Translations $copyWith({TranslationMetadata? meta}) => Translations(meta: meta ?? this.$meta); - - // Translations - late final TranslationsGenericEn generic = TranslationsGenericEn._(_root); - late final TranslationsOnboardingEn onboarding = TranslationsOnboardingEn._(_root); - late final TranslationsBookmarksEn bookmarks = TranslationsBookmarksEn._(_root); - late final TranslationsTagsEn tags = TranslationsTagsEn._(_root); - late final TranslationsSettingsEn settings = TranslationsSettingsEn._(_root); - late final TranslationsWebviewEn webview = TranslationsWebviewEn._(_root); - late final TranslationsColorsEn colors = TranslationsColorsEn._(_root); -} - -// Path: generic -class TranslationsGenericEn { - TranslationsGenericEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Confirm' - String get confirm => 'Confirm'; - - /// en: 'Cancel' - String get cancel => 'Cancel'; - - /// en: 'Next' - String get next => 'Next'; - - /// en: 'Save' - String get save => 'Save'; - - /// en: 'Close' - String get close => 'Close'; - - /// en: 'Error' - String get error => 'Error'; - - /// en: 'Optional' - String get optional => 'Optional'; - - /// en: 'Your authorization token is not valid anymore. Please, reauthenticate.' - String get authTokenNotValid => 'Your authorization token is not valid anymore. Please, reauthenticate.'; - - /// en: 'Options' - String get options => 'Options'; -} - -// Path: onboarding -class TranslationsOnboardingEn { - TranslationsOnboardingEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Welcome to Linkdy' - String get title => 'Welcome to Linkdy'; - - /// en: 'An application to manage your bookmarks.' - String get subtitle => 'An application to manage your bookmarks.'; - - /// en: 'Start' - String get start => 'Start'; - - /// en: 'Next' - String get next => 'Next'; - - /// en: 'Previous' - String get previous => 'Previous'; - - /// en: 'Server required' - String get serverRequired => 'Server required'; - - /// en: 'Linkdy it's not an standalone app, it requires the Linkding server to work. In order to use this application, you must deploy Linkding on your home server, VPS or any other computer.' - String get serverRequiredDescription => 'Linkdy it\'s not an standalone app, it requires the Linkding server to work.\nIn order to use this application, you must deploy Linkding on your home server, VPS or any other computer.'; - - /// en: 'Check the installation instructions on the official GitHub repository.' - String get installationInstructions => 'Check the installation instructions on the official GitHub repository.'; - - /// en: 'I confirm that I have an instance of the Linkding server already running.' - String get serverRunningConfirmation => 'I confirm that I have an instance of the Linkding server already running.'; - - /// en: 'Create a connection' - String get createConnection => 'Create a connection'; - - /// en: 'Enter all the required details to create a connection to your server.' - String get createConnectionSubtitle => 'Enter all the required details to create a connection to your server.'; - - /// en: 'IP address or domain' - String get ipAddressOrDomain => 'IP address or domain'; - - /// en: 'Port' - String get port => 'Port'; - - /// en: 'Path' - String get path => 'Path'; - - /// en: 'Invalid path' - String get invalidPath => 'Invalid path'; - - /// en: 'Token' - String get token => 'Token'; - - /// en: 'Required' - String get required => 'Required'; - - /// en: 'Server details' - String get serverDetails => 'Server details'; - - /// en: 'Authentication' - String get authentication => 'Authentication'; - - /// en: 'Test connection url' - String get testConnectionUrl => 'Test connection url'; - - /// en: 'Connection with server established' - String get connectionServerEstablished => 'Connection with server established'; - - /// en: 'Testing connection...' - String get testingConnection => 'Testing connection...'; - - /// en: 'Connection with server failed' - String get connectionServerFailed => 'Connection with server failed'; - - /// en: 'Connect' - String get connect => 'Connect'; - - /// en: 'Connecting...' - String get connecting => 'Connecting...'; - - /// en: 'Cannot connect to the server.' - String get cannotConnectToServer => 'Cannot connect to the server.'; - - /// en: 'Invalid token.' - String get invalidToken => 'Invalid token.'; - - /// en: 'Invalid IP address or domain' - String get invalidIpDomain => 'Invalid IP address or domain'; - - /// en: 'Invalid port' - String get invalidPort => 'Invalid port'; - - /// en: 'Token is required' - String get tokenRequired => 'Token is required'; -} - -// Path: bookmarks -class TranslationsBookmarksEn { - TranslationsBookmarksEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Bookmarks' - String get bookmarks => 'Bookmarks'; - - /// en: 'No bookmarks added' - String get noBookmarksAdded => 'No bookmarks added'; - - /// en: 'Cannot load the bookmarks' - String get cannotLoadBookmarks => 'Cannot load the bookmarks'; - - late final TranslationsBookmarksDatesEn dates = TranslationsBookmarksDatesEn._(_root); - - /// en: 'Shared' - String get shared => 'Shared'; - - /// en: 'Archived' - String get archived => 'Archived'; - - /// en: 'Show only read' - String get showOnlyRead => 'Show only read'; - - /// en: 'Show only unread' - String get showOnlyUnread => 'Show only unread'; - - /// en: 'Show all bookmarks' - String get showAllBookmarks => 'Show all bookmarks'; - - /// en: 'Read status' - String get readStatus => 'Read status'; - - /// en: 'All' - String get all => 'All'; - - /// en: 'Unread' - String get unread => 'Unread'; - - /// en: 'Read' - String get read => 'Read'; - - /// en: 'Filter and sort' - String get filterSort => 'Filter and sort'; - - /// en: 'Sorting' - String get sorting => 'Sorting'; - - /// en: 'Date' - String get date => 'Date'; - - /// en: 'Title' - String get title => 'Title'; - - /// en: 'Ascendant' - String get ascendant => 'Ascendant'; - - /// en: 'Descendant' - String get descendant => 'Descendant'; - - late final TranslationsBookmarksAddBookmarkEn addBookmark = TranslationsBookmarksAddBookmarkEn._(_root); - late final TranslationsBookmarksSearchEn search = TranslationsBookmarksSearchEn._(_root); - late final TranslationsBookmarksBookmarkOptionsEn bookmarkOptions = TranslationsBookmarksBookmarkOptionsEn._(_root); - late final TranslationsBookmarksShareOptionsEn shareOptions = TranslationsBookmarksShareOptionsEn._(_root); -} - -// Path: tags -class TranslationsTagsEn { - TranslationsTagsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Tags' - String get tags => 'Tags'; - - /// en: 'Created: $created' - String created({required Object created}) => 'Created: ${created}'; - - late final TranslationsTagsCreateTagEn createTag = TranslationsTagsCreateTagEn._(_root); - late final TranslationsTagsFilteredBookmarksEn filteredBookmarks = TranslationsTagsFilteredBookmarksEn._(_root); -} - -// Path: settings -class TranslationsSettingsEn { - TranslationsSettingsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Settings' - String get settings => 'Settings'; - - /// en: 'App settings' - String get appSettings => 'App settings'; - - /// en: 'About the app' - String get aboutApp => 'About the app'; - - /// en: 'App version' - String get appVersion => 'App version'; - - /// en: 'Created by' - String get createdBy => 'Created by'; - - /// en: 'Visit the application page at Google Play' - String get visitGooglePlay => 'Visit the application page at Google Play'; - - /// en: 'Visit the application repository at GitHub' - String get visitGitHubRepo => 'Visit the application repository at GitHub'; - - /// en: 'Linkding repository' - String get linkdingRepository => 'Linkding repository'; - - /// en: 'Link to the Linkding repository on GitHub' - String get linkdingRepositoryDescription => 'Link to the Linkding repository on GitHub'; - - /// en: 'More information about the app' - String get moreInfoApp => 'More information about the app'; - - /// en: 'Link to the app's information page' - String get moreInfoAppDescription => 'Link to the app\'s information page'; - - /// en: 'My other apps' - String get moreApps => 'My other apps'; - - /// en: 'More apps, contact, donations and more' - String get moreAppsDescription => 'More apps, contact, donations and more'; - - /// en: 'Select an option' - String get selectAnOption => 'Select an option'; - - late final TranslationsSettingsCustomizationEn customization = TranslationsSettingsCustomizationEn._(_root); - late final TranslationsSettingsGeneralSettingsEn generalSettings = TranslationsSettingsGeneralSettingsEn._(_root); -} - -// Path: webview -class TranslationsWebviewEn { - TranslationsWebviewEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Go back' - String get goBack => 'Go back'; - - /// en: 'Go forward' - String get goForward => 'Go forward'; - - /// en: 'Reload' - String get reload => 'Reload'; - - /// en: 'Open in system browser' - String get openInSystemBrowser => 'Open in system browser'; - - /// en: 'Copy link to clipboard' - String get copyLinkClipboard => 'Copy link to clipboard'; - - /// en: 'Link copied to the clipboard.' - String get linkCopiedClipboard => 'Link copied to the clipboard.'; - - /// en: 'Share' - String get share => 'Share'; - - /// en: 'The bookmark has invalid data or it's corrupted.' - String get invalidBookmarkData => 'The bookmark has invalid data or it\'s corrupted.'; -} - -// Path: colors -class TranslationsColorsEn { - TranslationsColorsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Red' - String get red => 'Red'; - - /// en: 'Green' - String get green => 'Green'; - - /// en: 'Blue' - String get blue => 'Blue'; - - /// en: 'Yellow' - String get yellow => 'Yellow'; - - /// en: 'Orange' - String get orange => 'Orange'; - - /// en: 'Brown' - String get brown => 'Brown'; - - /// en: 'Cyan' - String get cyan => 'Cyan'; - - /// en: 'Purple' - String get purple => 'Purple'; - - /// en: 'Pink' - String get pink => 'Pink'; - - /// en: 'Deep orange' - String get deepOrange => 'Deep orange'; - - /// en: 'Indigo' - String get indigo => 'Indigo'; -} - -// Path: bookmarks.dates -class TranslationsBookmarksDatesEn { - TranslationsBookmarksDatesEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Today, $time' - String todayAt({required Object time}) => 'Today, ${time}'; - - /// en: 'Yesterday, $time' - String yesterdayAt({required Object time}) => 'Yesterday, ${time}'; -} - -// Path: bookmarks.addBookmark -class TranslationsBookmarksAddBookmarkEn { - TranslationsBookmarksAddBookmarkEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Add new bookmark' - String get addBookmark => 'Add new bookmark'; - - /// en: 'Edit bookmark' - String get editBookmark => 'Edit bookmark'; - - /// en: 'Bookmark URL' - String get bookmarkUrl => 'Bookmark URL'; - - /// en: 'Bookmark details' - String get bookmarkDetails => 'Bookmark details'; - - /// en: 'Validate URL' - String get validateUrl => 'Validate URL'; - - /// en: 'The URL is valid' - String get urlValid => 'The URL is valid'; - - /// en: 'The URL is not valid' - String get urlNotValid => 'The URL is not valid'; - - /// en: 'The URL couldn't be checked, but you can save it anyway.' - String get cannotCheckUrl => 'The URL couldn\'t be checked, but you can save it anyway.'; - - /// en: 'Invalid URL' - String get invalidUrl => 'Invalid URL'; - - /// en: 'URL' - String get url => 'URL'; - - /// en: 'Checking URL...' - String get checkingUrl => 'Checking URL...'; - - /// en: 'Title' - String get title => 'Title'; - - /// en: 'Description' - String get description => 'Description'; - - /// en: 'Mark as unread' - String get markAsUnread => 'Mark as unread'; - - /// en: 'Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.' - String get markAsUnreadDescription => 'Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.'; - - /// en: 'Notes' - String get notes => 'Notes'; - - /// en: 'Add notes' - String get addNotes => 'Add notes'; - - /// en: 'Tags' - String get tags => 'Tags'; - - /// en: 'No tags added' - String get noTagsAdded => 'No tags added'; - - /// en: 'Tag cannot contain whitespaces' - String get tagNoWhitespaces => 'Tag cannot contain whitespaces'; - - /// en: 'Add tag' - String get addTag => 'Add tag'; - - /// en: 'Others' - String get others => 'Others'; - - /// en: 'Saving bookmark...' - String get savingBookmark => 'Saving bookmark...'; - - /// en: 'Bookmark saved successfully.' - String get bookmarkSavedSuccessfully => 'Bookmark saved successfully.'; - - /// en: 'An error occured when saving the new bookmark.' - String get errorSavingBookmark => 'An error occured when saving the new bookmark.'; - - /// en: 'Leave empty to use the website's title.' - String get leaveEmptyUseWebsiteTitle => 'Leave empty to use the website\'s title.'; - - /// en: 'Leave empty to use the website's description.' - String get leaveEmptyUseWebsiteDescription => 'Leave empty to use the website\'s description.'; - - /// en: 'Share' - String get share => 'Share'; - - /// en: 'Share this bookmark with other registered users and anonymous users.' - String get shareDescription => 'Share this bookmark with other registered users and anonymous users.'; - - /// en: 'This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark.' - String get urlAlreadyBookmarked => 'This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark.'; -} - -// Path: bookmarks.search -class TranslationsBookmarksSearchEn { - TranslationsBookmarksSearchEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Search bookmarks' - String get searchBookmarks => 'Search bookmarks'; - - /// en: 'Clear search' - String get clearSearch => 'Clear search'; - - /// en: 'Input a search term' - String get inputSearchTerm => 'Input a search term'; - - /// en: 'Cannot search content due to an error' - String get cannotSearchError => 'Cannot search content due to an error'; - - /// en: 'The inputted search term doesn't have any results' - String get inputtedSearchTermNoResults => 'The inputted search term doesn\'t have any results'; -} - -// Path: bookmarks.bookmarkOptions -class TranslationsBookmarksBookmarkOptionsEn { - TranslationsBookmarksBookmarkOptionsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Edit' - String get edit => 'Edit'; - - /// en: 'Delete' - String get delete => 'Delete'; - - /// en: 'Read' - String get read => 'Read'; - - /// en: 'Unread' - String get unread => 'Unread'; - - /// en: 'Mark as unread' - String get markAsUnread => 'Mark as unread'; - - /// en: 'Mark as read' - String get markAsRead => 'Mark as read'; - - /// en: 'Share options' - String get shareOptions => 'Share options'; - - /// en: 'Shared' - String get shared => 'Shared'; - - /// en: 'Archive' - String get archive => 'Archive'; - - /// en: 'Unarchive' - String get unarchive => 'Unarchive'; - - /// en: 'Deleting bookmark...' - String get deletingBookmark => 'Deleting bookmark...'; - - /// en: 'Bookmark deleted successfully' - String get bookmarkDeleted => 'Bookmark deleted successfully'; - - /// en: 'The bookmark couldn't be deleted due to an error.' - String get bookmarkNotDeleted => 'The bookmark couldn\'t be deleted due to an error.'; - - /// en: 'Delete bookmark' - String get deleteBookmark => 'Delete bookmark'; - - /// en: 'The following bookmark will be deleted:' - String get followingBookmarkDeleted => 'The following bookmark will be deleted:'; - - /// en: 'Marking as read...' - String get markingAsRead => 'Marking as read...'; - - /// en: 'Marking as unread...' - String get markingAsUnead => 'Marking as unread...'; - - /// en: 'Bookmark marked as read successfully.' - String get markedAsReadSuccessfully => 'Bookmark marked as read successfully.'; - - /// en: 'Bookmark marked as unread successfully.' - String get markedAsUnreadSuccessfully => 'Bookmark marked as unread successfully.'; - - /// en: 'The bookmark couldn't be marked as read.' - String get bookmarkNotMarkedAsRead => 'The bookmark couldn\'t be marked as read.'; - - /// en: 'The bookmark couldn't be marked as unread.' - String get bookmarkNotMarkedAsUnread => 'The bookmark couldn\'t be marked as unread.'; - - /// en: 'Archiving bookmark...' - String get archivingBookmark => 'Archiving bookmark...'; - - /// en: 'Unarchiving bookmark...' - String get unarchivingBookmark => 'Unarchiving bookmark...'; - - /// en: 'Bookmark archived successfully.' - String get bookmarkArchivedSuccessfully => 'Bookmark archived successfully.'; - - /// en: 'Bookmark unarchived successfully.' - String get bookmarkUnrchivedSuccessfully => 'Bookmark unarchived successfully.'; - - /// en: 'The bookmark couldn't be archived.' - String get bookmarkNotArchived => 'The bookmark couldn\'t be archived.'; - - /// en: 'The bookmark couldn't be unarchived.' - String get bookmarkNotUnrchived => 'The bookmark couldn\'t be unarchived.'; - - /// en: 'Share using a third party app' - String get shareThirdPartyApp => 'Share using a third party app'; - - /// en: 'Share internally' - String get shareInternally => 'Share internally'; - - /// en: 'Unshare internally' - String get unshareInternally => 'Unshare internally'; -} - -// Path: bookmarks.shareOptions -class TranslationsBookmarksShareOptionsEn { - TranslationsBookmarksShareOptionsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Share options' - String get shareOptions => 'Share options'; - - /// en: 'Share internally' - String get shareInternally => 'Share internally'; - - /// en: 'Unshare internally' - String get unshareInternally => 'Unshare internally'; - - /// en: 'Share internally with the rest of the users of this Linkding instance' - String get shareInternallyDescription => 'Share internally with the rest of the users of this Linkding instance'; - - /// en: 'Unshare this internally shared bookmark' - String get unshareInternallyDescription => 'Unshare this internally shared bookmark'; - - /// en: 'Share bookmark URL externally' - String get shareExternally => 'Share bookmark URL externally'; - - /// en: 'Share the bookmark URL externally using a third party application' - String get shareExternallyDescription => 'Share the bookmark URL externally using a third party application'; - - /// en: 'Sharing bookmark...' - String get sharingBookmark => 'Sharing bookmark...'; - - /// en: 'Unsharing bookmark...' - String get unsharingBookmark => 'Unsharing bookmark...'; - - /// en: 'Bookmark shared successfully.' - String get bookmarkSharedSuccessfully => 'Bookmark shared successfully.'; - - /// en: 'Bookmark couldn't be shared.' - String get bookmarkNotShared => 'Bookmark couldn\'t be shared.'; - - /// en: 'Bookmark unshared successfully.' - String get bookmarkUnsharedSuccessfully => 'Bookmark unshared successfully.'; - - /// en: 'Bookmark couldn't be unshared.' - String get bookmarkNotUnshared => 'Bookmark couldn\'t be unshared.'; -} - -// Path: tags.createTag -class TranslationsTagsCreateTagEn { - TranslationsTagsCreateTagEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Create tag' - String get createTag => 'Create tag'; - - /// en: 'Name' - String get name => 'Name'; - - /// en: 'Creating tag...' - String get creatingTag => 'Creating tag...'; - - /// en: 'An error occured when creating the tag.' - String get errorCreatingTag => 'An error occured when creating the tag.'; -} - -// Path: tags.filteredBookmarks -class TranslationsTagsFilteredBookmarksEn { - TranslationsTagsFilteredBookmarksEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'There are no bookmarks with this tag' - String get noBookmarksWithThisTag => 'There are no bookmarks with this tag'; - - /// en: 'There are no archived bookmarks' - String get noArchivedBookmarks => 'There are no archived bookmarks'; - - /// en: 'There are no shared bookmarks' - String get noSharedBookmarks => 'There are no shared bookmarks'; -} - -// Path: settings.customization -class TranslationsSettingsCustomizationEn { - TranslationsSettingsCustomizationEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Customization' - String get customization => 'Customization'; - - /// en: 'Set the app theme and color palette.' - String get customizationDescription => 'Set the app theme and color palette.'; - - /// en: 'Theme' - String get theme => 'Theme'; - - /// en: 'Light' - String get light => 'Light'; - - /// en: 'Dark' - String get dark => 'Dark'; - - /// en: 'System defined' - String get systemDefined => 'System defined'; - - /// en: 'Color' - String get color => 'Color'; - - /// en: 'Use dynamic theme' - String get useDynamicTheme => 'Use dynamic theme'; -} - -// Path: settings.generalSettings -class TranslationsSettingsGeneralSettingsEn { - TranslationsSettingsGeneralSettingsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'General settings' - String get generalSettings => 'General settings'; - - /// en: 'General tweaks for the application.' - String get generalSettingsDescription => 'General tweaks for the application.'; - - /// en: 'Bookmarks' - String get bookmarks => 'Bookmarks'; - - /// en: 'Show favicon' - String get showFavicon => 'Show favicon'; - - /// en: 'Show the website's favicon on each bookmark.' - String get showFaviconDescription => 'Show the website\'s favicon on each bookmark.'; - - /// en: 'Disconnect from server' - String get disconnectFromServer => 'Disconnect from server'; - - late final TranslationsSettingsGeneralSettingsDisconnectModalEn disconnectModal = TranslationsSettingsGeneralSettingsDisconnectModalEn._(_root); - - /// en: 'Use in app browser' - String get useInAppBrowser => 'Use in app browser'; - - /// en: 'Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used.' - String get useInAppBrowserDescription => 'Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used.'; - - /// en: 'Open links with...' - String get openLinksWith => 'Open links with...'; - - /// en: 'App internal browser' - String get internalBrowser => 'App internal browser'; - - /// en: 'Browser custom tab' - String get browserCustomTab => 'Browser custom tab'; - - /// en: 'System browser' - String get systemBrowser => 'System browser'; - - /// en: 'Tags' - String get tags => 'Tags'; - - late final TranslationsSettingsGeneralSettingsDefaultTagsEn defaultTags = TranslationsSettingsGeneralSettingsDefaultTagsEn._(_root); - - /// en: 'Others' - String get others => 'Others'; - - /// en: 'Set mark as unread by default' - String get setMarkAsUnreadDefault => 'Set mark as unread by default'; - - /// en: 'Set the mark as unread option by default when creating a new bookmark.' - String get setMarkAsUnreadDefaultDescription => 'Set the mark as unread option by default when creating a new bookmark.'; - - /// en: 'Enable slide options' - String get enableSlideOptions => 'Enable slide options'; - - /// en: 'Enable slide options on the bookmark list' - String get enableSlideOptionsDescription => 'Enable slide options on the bookmark list'; -} - -// Path: settings.generalSettings.disconnectModal -class TranslationsSettingsGeneralSettingsDisconnectModalEn { - TranslationsSettingsGeneralSettingsDisconnectModalEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Disconnect' - String get title => 'Disconnect'; - - /// en: 'Are you sure you want to disconnect from the server? You will be redirected to the initial setup.' - String get description => 'Are you sure you want to disconnect from the server?\nYou will be redirected to the initial setup.'; -} - -// Path: settings.generalSettings.defaultTags -class TranslationsSettingsGeneralSettingsDefaultTagsEn { - TranslationsSettingsGeneralSettingsDefaultTagsEn._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - - /// en: 'Default tags' - String get defaultTags => 'Default tags'; - - /// en: 'Define a list of tags that will be added by default when creating a bookmark' - String get defaultTagsDescription => 'Define a list of tags that will be added by default when creating a bookmark'; - - /// en: 'New tag' - String get newTag => 'New tag'; - - /// en: 'Add tag' - String get addTag => 'Add tag'; - - /// en: 'Remove this tag' - String get removeThisTag => 'Remove this tag'; - - /// en: 'There are no default tags' - String get noDefaultTags => 'There are no default tags'; -} - -/// The flat map containing all translations for locale . -/// Only for edge cases! For simple maps, use the map function of this library. -/// -/// The Dart AOT compiler has issues with very large switch statements, -/// so the map is split into smaller functions (512 entries each). -extension on Translations { - dynamic _flatMapFunction(String path) { - return switch (path) { - 'generic.confirm' => 'Confirm', - 'generic.cancel' => 'Cancel', - 'generic.next' => 'Next', - 'generic.save' => 'Save', - 'generic.close' => 'Close', - 'generic.error' => 'Error', - 'generic.optional' => 'Optional', - 'generic.authTokenNotValid' => 'Your authorization token is not valid anymore. Please, reauthenticate.', - 'generic.options' => 'Options', - 'onboarding.title' => 'Welcome to Linkdy', - 'onboarding.subtitle' => 'An application to manage your bookmarks.', - 'onboarding.start' => 'Start', - 'onboarding.next' => 'Next', - 'onboarding.previous' => 'Previous', - 'onboarding.serverRequired' => 'Server required', - 'onboarding.serverRequiredDescription' => 'Linkdy it\'s not an standalone app, it requires the Linkding server to work.\nIn order to use this application, you must deploy Linkding on your home server, VPS or any other computer.', - 'onboarding.installationInstructions' => 'Check the installation instructions on the official GitHub repository.', - 'onboarding.serverRunningConfirmation' => 'I confirm that I have an instance of the Linkding server already running.', - 'onboarding.createConnection' => 'Create a connection', - 'onboarding.createConnectionSubtitle' => 'Enter all the required details to create a connection to your server.', - 'onboarding.ipAddressOrDomain' => 'IP address or domain', - 'onboarding.port' => 'Port', - 'onboarding.path' => 'Path', - 'onboarding.invalidPath' => 'Invalid path', - 'onboarding.token' => 'Token', - 'onboarding.required' => 'Required', - 'onboarding.serverDetails' => 'Server details', - 'onboarding.authentication' => 'Authentication', - 'onboarding.testConnectionUrl' => 'Test connection url', - 'onboarding.connectionServerEstablished' => 'Connection with server established', - 'onboarding.testingConnection' => 'Testing connection...', - 'onboarding.connectionServerFailed' => 'Connection with server failed', - 'onboarding.connect' => 'Connect', - 'onboarding.connecting' => 'Connecting...', - 'onboarding.cannotConnectToServer' => 'Cannot connect to the server.', - 'onboarding.invalidToken' => 'Invalid token.', - 'onboarding.invalidIpDomain' => 'Invalid IP address or domain', - 'onboarding.invalidPort' => 'Invalid port', - 'onboarding.tokenRequired' => 'Token is required', - 'bookmarks.bookmarks' => 'Bookmarks', - 'bookmarks.noBookmarksAdded' => 'No bookmarks added', - 'bookmarks.cannotLoadBookmarks' => 'Cannot load the bookmarks', - 'bookmarks.dates.todayAt' => ({required Object time}) => 'Today, ${time}', - 'bookmarks.dates.yesterdayAt' => ({required Object time}) => 'Yesterday, ${time}', - 'bookmarks.shared' => 'Shared', - 'bookmarks.archived' => 'Archived', - 'bookmarks.showOnlyRead' => 'Show only read', - 'bookmarks.showOnlyUnread' => 'Show only unread', - 'bookmarks.showAllBookmarks' => 'Show all bookmarks', - 'bookmarks.readStatus' => 'Read status', - 'bookmarks.all' => 'All', - 'bookmarks.unread' => 'Unread', - 'bookmarks.read' => 'Read', - 'bookmarks.filterSort' => 'Filter and sort', - 'bookmarks.sorting' => 'Sorting', - 'bookmarks.date' => 'Date', - 'bookmarks.title' => 'Title', - 'bookmarks.ascendant' => 'Ascendant', - 'bookmarks.descendant' => 'Descendant', - 'bookmarks.addBookmark.addBookmark' => 'Add new bookmark', - 'bookmarks.addBookmark.editBookmark' => 'Edit bookmark', - 'bookmarks.addBookmark.bookmarkUrl' => 'Bookmark URL', - 'bookmarks.addBookmark.bookmarkDetails' => 'Bookmark details', - 'bookmarks.addBookmark.validateUrl' => 'Validate URL', - 'bookmarks.addBookmark.urlValid' => 'The URL is valid', - 'bookmarks.addBookmark.urlNotValid' => 'The URL is not valid', - 'bookmarks.addBookmark.cannotCheckUrl' => 'The URL couldn\'t be checked, but you can save it anyway.', - 'bookmarks.addBookmark.invalidUrl' => 'Invalid URL', - 'bookmarks.addBookmark.url' => 'URL', - 'bookmarks.addBookmark.checkingUrl' => 'Checking URL...', - 'bookmarks.addBookmark.title' => 'Title', - 'bookmarks.addBookmark.description' => 'Description', - 'bookmarks.addBookmark.markAsUnread' => 'Mark as unread', - 'bookmarks.addBookmark.markAsUnreadDescription' => 'Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.', - 'bookmarks.addBookmark.notes' => 'Notes', - 'bookmarks.addBookmark.addNotes' => 'Add notes', - 'bookmarks.addBookmark.tags' => 'Tags', - 'bookmarks.addBookmark.noTagsAdded' => 'No tags added', - 'bookmarks.addBookmark.tagNoWhitespaces' => 'Tag cannot contain whitespaces', - 'bookmarks.addBookmark.addTag' => 'Add tag', - 'bookmarks.addBookmark.others' => 'Others', - 'bookmarks.addBookmark.savingBookmark' => 'Saving bookmark...', - 'bookmarks.addBookmark.bookmarkSavedSuccessfully' => 'Bookmark saved successfully.', - 'bookmarks.addBookmark.errorSavingBookmark' => 'An error occured when saving the new bookmark.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteTitle' => 'Leave empty to use the website\'s title.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteDescription' => 'Leave empty to use the website\'s description.', - 'bookmarks.addBookmark.share' => 'Share', - 'bookmarks.addBookmark.shareDescription' => 'Share this bookmark with other registered users and anonymous users.', - 'bookmarks.addBookmark.urlAlreadyBookmarked' => 'This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark.', - 'bookmarks.search.searchBookmarks' => 'Search bookmarks', - 'bookmarks.search.clearSearch' => 'Clear search', - 'bookmarks.search.inputSearchTerm' => 'Input a search term', - 'bookmarks.search.cannotSearchError' => 'Cannot search content due to an error', - 'bookmarks.search.inputtedSearchTermNoResults' => 'The inputted search term doesn\'t have any results', - 'bookmarks.bookmarkOptions.edit' => 'Edit', - 'bookmarks.bookmarkOptions.delete' => 'Delete', - 'bookmarks.bookmarkOptions.read' => 'Read', - 'bookmarks.bookmarkOptions.unread' => 'Unread', - 'bookmarks.bookmarkOptions.markAsUnread' => 'Mark as unread', - 'bookmarks.bookmarkOptions.markAsRead' => 'Mark as read', - 'bookmarks.bookmarkOptions.shareOptions' => 'Share options', - 'bookmarks.bookmarkOptions.shared' => 'Shared', - 'bookmarks.bookmarkOptions.archive' => 'Archive', - 'bookmarks.bookmarkOptions.unarchive' => 'Unarchive', - 'bookmarks.bookmarkOptions.deletingBookmark' => 'Deleting bookmark...', - 'bookmarks.bookmarkOptions.bookmarkDeleted' => 'Bookmark deleted successfully', - 'bookmarks.bookmarkOptions.bookmarkNotDeleted' => 'The bookmark couldn\'t be deleted due to an error.', - 'bookmarks.bookmarkOptions.deleteBookmark' => 'Delete bookmark', - 'bookmarks.bookmarkOptions.followingBookmarkDeleted' => 'The following bookmark will be deleted:', - 'bookmarks.bookmarkOptions.markingAsRead' => 'Marking as read...', - 'bookmarks.bookmarkOptions.markingAsUnead' => 'Marking as unread...', - 'bookmarks.bookmarkOptions.markedAsReadSuccessfully' => 'Bookmark marked as read successfully.', - 'bookmarks.bookmarkOptions.markedAsUnreadSuccessfully' => 'Bookmark marked as unread successfully.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead' => 'The bookmark couldn\'t be marked as read.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread' => 'The bookmark couldn\'t be marked as unread.', - 'bookmarks.bookmarkOptions.archivingBookmark' => 'Archiving bookmark...', - 'bookmarks.bookmarkOptions.unarchivingBookmark' => 'Unarchiving bookmark...', - 'bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully' => 'Bookmark archived successfully.', - 'bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully' => 'Bookmark unarchived successfully.', - 'bookmarks.bookmarkOptions.bookmarkNotArchived' => 'The bookmark couldn\'t be archived.', - 'bookmarks.bookmarkOptions.bookmarkNotUnrchived' => 'The bookmark couldn\'t be unarchived.', - 'bookmarks.bookmarkOptions.shareThirdPartyApp' => 'Share using a third party app', - 'bookmarks.bookmarkOptions.shareInternally' => 'Share internally', - 'bookmarks.bookmarkOptions.unshareInternally' => 'Unshare internally', - 'bookmarks.shareOptions.shareOptions' => 'Share options', - 'bookmarks.shareOptions.shareInternally' => 'Share internally', - 'bookmarks.shareOptions.unshareInternally' => 'Unshare internally', - 'bookmarks.shareOptions.shareInternallyDescription' => 'Share internally with the rest of the users of this Linkding instance', - 'bookmarks.shareOptions.unshareInternallyDescription' => 'Unshare this internally shared bookmark', - 'bookmarks.shareOptions.shareExternally' => 'Share bookmark URL externally', - 'bookmarks.shareOptions.shareExternallyDescription' => 'Share the bookmark URL externally using a third party application', - 'bookmarks.shareOptions.sharingBookmark' => 'Sharing bookmark...', - 'bookmarks.shareOptions.unsharingBookmark' => 'Unsharing bookmark...', - 'bookmarks.shareOptions.bookmarkSharedSuccessfully' => 'Bookmark shared successfully.', - 'bookmarks.shareOptions.bookmarkNotShared' => 'Bookmark couldn\'t be shared.', - 'bookmarks.shareOptions.bookmarkUnsharedSuccessfully' => 'Bookmark unshared successfully.', - 'bookmarks.shareOptions.bookmarkNotUnshared' => 'Bookmark couldn\'t be unshared.', - 'tags.tags' => 'Tags', - 'tags.created' => ({required Object created}) => 'Created: ${created}', - 'tags.createTag.createTag' => 'Create tag', - 'tags.createTag.name' => 'Name', - 'tags.createTag.creatingTag' => 'Creating tag...', - 'tags.createTag.errorCreatingTag' => 'An error occured when creating the tag.', - 'tags.filteredBookmarks.noBookmarksWithThisTag' => 'There are no bookmarks with this tag', - 'tags.filteredBookmarks.noArchivedBookmarks' => 'There are no archived bookmarks', - 'tags.filteredBookmarks.noSharedBookmarks' => 'There are no shared bookmarks', - 'settings.settings' => 'Settings', - 'settings.appSettings' => 'App settings', - 'settings.aboutApp' => 'About the app', - 'settings.appVersion' => 'App version', - 'settings.createdBy' => 'Created by', - 'settings.visitGooglePlay' => 'Visit the application page at Google Play', - 'settings.visitGitHubRepo' => 'Visit the application repository at GitHub', - 'settings.linkdingRepository' => 'Linkding repository', - 'settings.linkdingRepositoryDescription' => 'Link to the Linkding repository on GitHub', - 'settings.moreInfoApp' => 'More information about the app', - 'settings.moreInfoAppDescription' => 'Link to the app\'s information page', - 'settings.moreApps' => 'My other apps', - 'settings.moreAppsDescription' => 'More apps, contact, donations and more', - 'settings.selectAnOption' => 'Select an option', - 'settings.customization.customization' => 'Customization', - 'settings.customization.customizationDescription' => 'Set the app theme and color palette.', - 'settings.customization.theme' => 'Theme', - 'settings.customization.light' => 'Light', - 'settings.customization.dark' => 'Dark', - 'settings.customization.systemDefined' => 'System defined', - 'settings.customization.color' => 'Color', - 'settings.customization.useDynamicTheme' => 'Use dynamic theme', - 'settings.generalSettings.generalSettings' => 'General settings', - 'settings.generalSettings.generalSettingsDescription' => 'General tweaks for the application.', - 'settings.generalSettings.bookmarks' => 'Bookmarks', - 'settings.generalSettings.showFavicon' => 'Show favicon', - 'settings.generalSettings.showFaviconDescription' => 'Show the website\'s favicon on each bookmark.', - 'settings.generalSettings.disconnectFromServer' => 'Disconnect from server', - 'settings.generalSettings.disconnectModal.title' => 'Disconnect', - 'settings.generalSettings.disconnectModal.description' => 'Are you sure you want to disconnect from the server?\nYou will be redirected to the initial setup.', - 'settings.generalSettings.useInAppBrowser' => 'Use in app browser', - 'settings.generalSettings.useInAppBrowserDescription' => 'Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used.', - 'settings.generalSettings.openLinksWith' => 'Open links with...', - 'settings.generalSettings.internalBrowser' => 'App internal browser', - 'settings.generalSettings.browserCustomTab' => 'Browser custom tab', - 'settings.generalSettings.systemBrowser' => 'System browser', - 'settings.generalSettings.tags' => 'Tags', - 'settings.generalSettings.defaultTags.defaultTags' => 'Default tags', - 'settings.generalSettings.defaultTags.defaultTagsDescription' => 'Define a list of tags that will be added by default when creating a bookmark', - 'settings.generalSettings.defaultTags.newTag' => 'New tag', - 'settings.generalSettings.defaultTags.addTag' => 'Add tag', - 'settings.generalSettings.defaultTags.removeThisTag' => 'Remove this tag', - 'settings.generalSettings.defaultTags.noDefaultTags' => 'There are no default tags', - 'settings.generalSettings.others' => 'Others', - 'settings.generalSettings.setMarkAsUnreadDefault' => 'Set mark as unread by default', - 'settings.generalSettings.setMarkAsUnreadDefaultDescription' => 'Set the mark as unread option by default when creating a new bookmark.', - 'settings.generalSettings.enableSlideOptions' => 'Enable slide options', - 'settings.generalSettings.enableSlideOptionsDescription' => 'Enable slide options on the bookmark list', - 'webview.goBack' => 'Go back', - 'webview.goForward' => 'Go forward', - 'webview.reload' => 'Reload', - 'webview.openInSystemBrowser' => 'Open in system browser', - 'webview.copyLinkClipboard' => 'Copy link to clipboard', - 'webview.linkCopiedClipboard' => 'Link copied to the clipboard.', - 'webview.share' => 'Share', - 'webview.invalidBookmarkData' => 'The bookmark has invalid data or it\'s corrupted.', - 'colors.red' => 'Red', - 'colors.green' => 'Green', - 'colors.blue' => 'Blue', - 'colors.yellow' => 'Yellow', - 'colors.orange' => 'Orange', - 'colors.brown' => 'Brown', - 'colors.cyan' => 'Cyan', - 'colors.purple' => 'Purple', - 'colors.pink' => 'Pink', - 'colors.deepOrange' => 'Deep orange', - 'colors.indigo' => 'Indigo', - _ => null, - }; - } -} diff --git a/lib/i18n/strings_en.i18n.json b/lib/i18n/strings_en.i18n.json deleted file mode 100644 index f922b9e..0000000 --- a/lib/i18n/strings_en.i18n.json +++ /dev/null @@ -1,251 +0,0 @@ -{ - "generic": { - "confirm": "Confirm", - "cancel": "Cancel", - "next": "Next", - "save": "Save", - "close": "Close", - "error": "Error", - "optional": "Optional", - "authTokenNotValid": "Your authorization token is not valid anymore. Please, reauthenticate.", - "options": "Options" - }, - "onboarding": { - "title": "Welcome to Linkdy", - "subtitle": "An application to manage your bookmarks.", - "start": "Start", - "next": "Next", - "previous": "Previous", - "serverRequired": "Server required", - "serverRequiredDescription": "Linkdy it's not an standalone app, it requires the Linkding server to work.\nIn order to use this application, you must deploy Linkding on your home server, VPS or any other computer.", - "installationInstructions": "Check the installation instructions on the official GitHub repository.", - "serverRunningConfirmation": "I confirm that I have an instance of the Linkding server already running.", - "createConnection": "Create a connection", - "createConnectionSubtitle": "Enter all the required details to create a connection to your server.", - "ipAddressOrDomain": "IP address or domain", - "port": "Port", - "path": "Path", - "invalidPath": "Invalid path", - "token": "Token", - "required": "Required", - "serverDetails": "Server details", - "authentication": "Authentication", - "testConnectionUrl": "Test connection url", - "connectionServerEstablished": "Connection with server established", - "testingConnection": "Testing connection...", - "connectionServerFailed": "Connection with server failed", - "connect": "Connect", - "connecting": "Connecting...", - "cannotConnectToServer": "Cannot connect to the server.", - "invalidToken": "Invalid token.", - "invalidIpDomain": "Invalid IP address or domain", - "invalidPort": "Invalid port", - "tokenRequired": "Token is required" - }, - "bookmarks": { - "bookmarks": "Bookmarks", - "noBookmarksAdded": "No bookmarks added", - "cannotLoadBookmarks": "Cannot load the bookmarks", - "dates": { - "todayAt": "Today, $time", - "yesterdayAt": "Yesterday, $time" - }, - "shared": "Shared", - "archived": "Archived", - "showOnlyRead": "Show only read", - "showOnlyUnread": "Show only unread", - "showAllBookmarks": "Show all bookmarks", - "readStatus": "Read status", - "all": "All", - "unread": "Unread", - "read": "Read", - "filterSort": "Filter and sort", - "sorting": "Sorting", - "date": "Date", - "title": "Title", - "ascendant": "Ascendant", - "descendant": "Descendant", - "addBookmark": { - "addBookmark": "Add new bookmark", - "editBookmark": "Edit bookmark", - "bookmarkUrl": "Bookmark URL", - "bookmarkDetails": "Bookmark details", - "validateUrl": "Validate URL", - "urlValid": "The URL is valid", - "urlNotValid": "The URL is not valid", - "cannotCheckUrl": "The URL couldn't be checked, but you can save it anyway.", - "invalidUrl": "Invalid URL", - "url": "URL", - "checkingUrl": "Checking URL...", - "title": "Title", - "description": "Description", - "markAsUnread": "Mark as unread", - "markAsUnreadDescription": "Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.", - "notes": "Notes", - "addNotes": "Add notes", - "tags": "Tags", - "noTagsAdded": "No tags added", - "tagNoWhitespaces": "Tag cannot contain whitespaces", - "addTag": "Add tag", - "others": "Others", - "savingBookmark": "Saving bookmark...", - "bookmarkSavedSuccessfully": "Bookmark saved successfully.", - "errorSavingBookmark": "An error occured when saving the new bookmark.", - "leaveEmptyUseWebsiteTitle": "Leave empty to use the website's title.", - "leaveEmptyUseWebsiteDescription": "Leave empty to use the website's description.", - "share": "Share", - "shareDescription": "Share this bookmark with other registered users and anonymous users.", - "urlAlreadyBookmarked": "This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark." - }, - "search": { - "searchBookmarks": "Search bookmarks", - "clearSearch": "Clear search", - "inputSearchTerm": "Input a search term", - "cannotSearchError": "Cannot search content due to an error", - "inputtedSearchTermNoResults": "The inputted search term doesn't have any results" - }, - "bookmarkOptions": { - "edit": "Edit", - "delete": "Delete", - "read": "Read", - "unread": "Unread", - "markAsUnread": "Mark as unread", - "markAsRead": "Mark as read", - "shareOptions": "Share options", - "shared": "Shared", - "archive": "Archive", - "unarchive": "Unarchive", - "deletingBookmark": "Deleting bookmark...", - "bookmarkDeleted": "Bookmark deleted successfully", - "bookmarkNotDeleted": "The bookmark couldn't be deleted due to an error.", - "deleteBookmark": "Delete bookmark", - "followingBookmarkDeleted": "The following bookmark will be deleted:", - "markingAsRead": "Marking as read...", - "markingAsUnead": "Marking as unread...", - "markedAsReadSuccessfully": "Bookmark marked as read successfully.", - "markedAsUnreadSuccessfully": "Bookmark marked as unread successfully.", - "bookmarkNotMarkedAsRead": "The bookmark couldn't be marked as read.", - "bookmarkNotMarkedAsUnread": "The bookmark couldn't be marked as unread.", - "archivingBookmark": "Archiving bookmark...", - "unarchivingBookmark": "Unarchiving bookmark...", - "bookmarkArchivedSuccessfully": "Bookmark archived successfully.", - "bookmarkUnrchivedSuccessfully": "Bookmark unarchived successfully.", - "bookmarkNotArchived": "The bookmark couldn't be archived.", - "bookmarkNotUnrchived": "The bookmark couldn't be unarchived.", - "shareThirdPartyApp": "Share using a third party app", - "shareInternally": "Share internally", - "unshareInternally": "Unshare internally" - }, - "shareOptions": { - "shareOptions": "Share options", - "shareInternally": "Share internally", - "unshareInternally": "Unshare internally", - "shareInternallyDescription": "Share internally with the rest of the users of this Linkding instance", - "unshareInternallyDescription": "Unshare this internally shared bookmark", - "shareExternally": "Share bookmark URL externally", - "shareExternallyDescription": "Share the bookmark URL externally using a third party application", - "sharingBookmark": "Sharing bookmark...", - "unsharingBookmark": "Unsharing bookmark...", - "bookmarkSharedSuccessfully": "Bookmark shared successfully.", - "bookmarkNotShared": "Bookmark couldn't be shared.", - "bookmarkUnsharedSuccessfully": "Bookmark unshared successfully.", - "bookmarkNotUnshared": "Bookmark couldn't be unshared." - } - }, - "tags": { - "tags": "Tags", - "created": "Created: $created", - "createTag": { - "createTag": "Create tag", - "name": "Name", - "creatingTag": "Creating tag...", - "errorCreatingTag": "An error occured when creating the tag." - }, - "filteredBookmarks": { - "noBookmarksWithThisTag": "There are no bookmarks with this tag", - "noArchivedBookmarks": "There are no archived bookmarks", - "noSharedBookmarks": "There are no shared bookmarks" - } - }, - "settings": { - "settings": "Settings", - "appSettings": "App settings", - "aboutApp": "About the app", - "appVersion": "App version", - "createdBy": "Created by", - "visitGooglePlay": "Visit the application page at Google Play", - "visitGitHubRepo": "Visit the application repository at GitHub", - "linkdingRepository": "Linkding repository", - "linkdingRepositoryDescription": "Link to the Linkding repository on GitHub", - "moreInfoApp": "More information about the app", - "moreInfoAppDescription": "Link to the app's information page", - "moreApps": "My other apps", - "moreAppsDescription": "More apps, contact, donations and more", - "selectAnOption": "Select an option", - "customization": { - "customization": "Customization", - "customizationDescription": "Set the app theme and color palette.", - "theme": "Theme", - "light": "Light", - "dark": "Dark", - "systemDefined": "System defined", - "color": "Color", - "useDynamicTheme": "Use dynamic theme" - }, - "generalSettings": { - "generalSettings": "General settings", - "generalSettingsDescription": "General tweaks for the application.", - "bookmarks": "Bookmarks", - "showFavicon": "Show favicon", - "showFaviconDescription": "Show the website's favicon on each bookmark.", - "disconnectFromServer": "Disconnect from server", - "disconnectModal": { - "title": "Disconnect", - "description": "Are you sure you want to disconnect from the server?\nYou will be redirected to the initial setup." - }, - "useInAppBrowser": "Use in app browser", - "useInAppBrowserDescription": "Opens the bookmarks with the integrated browser instead of with the system browser. On tablet mode the internal browser will always be used.", - "openLinksWith": "Open links with...", - "internalBrowser": "App internal browser", - "browserCustomTab": "Browser custom tab", - "systemBrowser": "System browser", - "tags": "Tags", - "defaultTags": { - "defaultTags": "Default tags", - "defaultTagsDescription": "Define a list of tags that will be added by default when creating a bookmark", - "newTag": "New tag", - "addTag": "Add tag", - "removeThisTag": "Remove this tag", - "noDefaultTags": "There are no default tags" - }, - "others": "Others", - "setMarkAsUnreadDefault": "Set mark as unread by default", - "setMarkAsUnreadDefaultDescription": "Set the mark as unread option by default when creating a new bookmark.", - "enableSlideOptions": "Enable slide options", - "enableSlideOptionsDescription": "Enable slide options on the bookmark list" - } - }, - "webview": { - "goBack": "Go back", - "goForward": "Go forward", - "reload": "Reload", - "openInSystemBrowser": "Open in system browser", - "copyLinkClipboard": "Copy link to clipboard", - "linkCopiedClipboard": "Link copied to the clipboard.", - "share": "Share", - "invalidBookmarkData": "The bookmark has invalid data or it's corrupted." - }, - "colors": { - "red": "Red", - "green": "Green", - "blue": "Blue", - "yellow": "Yellow", - "orange": "Orange", - "brown": "Brown", - "cyan": "Cyan", - "purple": "Purple", - "pink": "Pink", - "deepOrange": "Deep orange", - "indigo": "Indigo" - } -} \ No newline at end of file diff --git a/lib/i18n/strings_es.g.dart b/lib/i18n/strings_es.g.dart deleted file mode 100644 index c7d3d83..0000000 --- a/lib/i18n/strings_es.g.dart +++ /dev/null @@ -1,659 +0,0 @@ -/// -/// Generated file. Do not edit. -/// -// coverage:ignore-file -// ignore_for_file: type=lint, unused_import -// dart format off - -import 'package:flutter/widgets.dart'; -import 'package:intl/intl.dart'; -import 'package:slang/generated.dart'; -import 'strings.g.dart'; - -// Path: -class TranslationsEs with BaseTranslations implements Translations { - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - TranslationsEs({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver, TranslationMetadata? meta}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = meta ?? TranslationMetadata( - locale: AppLocale.es, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ) { - $meta.setFlatMapFunction(_flatMapFunction); - } - - /// Metadata for the translations of . - @override final TranslationMetadata $meta; - - /// Access flat map - @override dynamic operator[](String key) => $meta.getTranslation(key); - - late final TranslationsEs _root = this; // ignore: unused_field - - @override - TranslationsEs $copyWith({TranslationMetadata? meta}) => TranslationsEs(meta: meta ?? this.$meta); - - // Translations - @override late final _TranslationsGenericEs generic = _TranslationsGenericEs._(_root); - @override late final _TranslationsOnboardingEs onboarding = _TranslationsOnboardingEs._(_root); - @override late final _TranslationsBookmarksEs bookmarks = _TranslationsBookmarksEs._(_root); - @override late final _TranslationsTagsEs tags = _TranslationsTagsEs._(_root); - @override late final _TranslationsSettingsEs settings = _TranslationsSettingsEs._(_root); - @override late final _TranslationsWebviewEs webview = _TranslationsWebviewEs._(_root); - @override late final _TranslationsColorsEs colors = _TranslationsColorsEs._(_root); -} - -// Path: generic -class _TranslationsGenericEs implements TranslationsGenericEn { - _TranslationsGenericEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get confirm => 'Confirmar'; - @override String get cancel => 'Cancelar'; - @override String get next => 'Siguiente'; - @override String get save => 'Guardar'; - @override String get close => 'Cerrar'; - @override String get error => 'Error'; - @override String get optional => 'Opcional'; - @override String get authTokenNotValid => 'Su token de autorización ya no es válido. Por favor, vuelva a autenticarse.'; - @override String get options => 'Opciones'; -} - -// Path: onboarding -class _TranslationsOnboardingEs implements TranslationsOnboardingEn { - _TranslationsOnboardingEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get title => 'Bienvenido a Linkdy'; - @override String get subtitle => 'Una aplicación para gestionar tus enlaces favoritos.'; - @override String get start => 'Comenzar'; - @override String get next => 'Siguiente'; - @override String get previous => 'Anterior'; - @override String get serverRequired => 'Servidor requerido'; - @override String get serverRequiredDescription => 'Linkdy no es una aplicación independiente, requiere el servidor Linkding para funcionar.\nPara utilizar esta aplicación, debe instalar Linkding en su servidor doméstico, VPS o cualquier otro ordenador.'; - @override String get installationInstructions => 'Mira las instrucciones de instalación en el repositorio oficial en GitHub.'; - @override String get serverRunningConfirmation => 'Confirmo que tengo una instancia del servidor Linkding ya en funcionamiento.'; - @override String get createConnection => 'Crear una conexión'; - @override String get createConnectionSubtitle => 'Introduce todos los detalles requeridos para crear una conexión con el servidor'; - @override String get ipAddressOrDomain => 'Dirección IP o dominio'; - @override String get port => 'Puerto'; - @override String get path => 'Ruta'; - @override String get invalidPath => 'Ruta no válida'; - @override String get token => 'Token'; - @override String get required => 'Requerido'; - @override String get serverDetails => 'Detalles del servidor'; - @override String get authentication => 'Autenticación'; - @override String get testConnectionUrl => 'Probar URL de conexión'; - @override String get testingConnection => 'Probando conexión...'; - @override String get connectionServerEstablished => 'Conexión con servidor establecida'; - @override String get connectionServerFailed => 'Conexión con servidor fallida'; - @override String get connect => 'Conectar'; - @override String get connecting => 'Conectando...'; - @override String get cannotConnectToServer => 'No se puede conectar con el servidor.'; - @override String get invalidToken => 'Token no válido.'; - @override String get invalidIpDomain => 'Dirección IP o dominio no válido'; - @override String get invalidPort => 'Puerto no válido'; - @override String get tokenRequired => 'Token requerido'; -} - -// Path: bookmarks -class _TranslationsBookmarksEs implements TranslationsBookmarksEn { - _TranslationsBookmarksEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get bookmarks => 'Marcadores'; - @override String get noBookmarksAdded => 'No hay marcadores añadidos'; - @override String get cannotLoadBookmarks => 'No se pueden cargar los marcadores'; - @override late final _TranslationsBookmarksDatesEs dates = _TranslationsBookmarksDatesEs._(_root); - @override String get shared => 'Compartidos'; - @override String get archived => 'Archivados'; - @override String get showOnlyRead => 'Mostrar solo leídos'; - @override String get showOnlyUnread => 'Mostrar solo no leídos'; - @override String get showAllBookmarks => 'Mostrar todos los marcadores'; - @override String get readStatus => 'Estado de lectura'; - @override String get all => 'Todos'; - @override String get unread => 'No leídos'; - @override String get read => 'Leídos'; - @override String get filterSort => 'Filtrar y ordenar'; - @override String get sorting => 'Ordenación'; - @override String get date => 'Fecha'; - @override String get title => 'Título'; - @override String get ascendant => 'Ascendiente'; - @override String get descendant => 'Descendiente'; - @override late final _TranslationsBookmarksAddBookmarkEs addBookmark = _TranslationsBookmarksAddBookmarkEs._(_root); - @override late final _TranslationsBookmarksSearchEs search = _TranslationsBookmarksSearchEs._(_root); - @override late final _TranslationsBookmarksBookmarkOptionsEs bookmarkOptions = _TranslationsBookmarksBookmarkOptionsEs._(_root); - @override late final _TranslationsBookmarksShareOptionsEs shareOptions = _TranslationsBookmarksShareOptionsEs._(_root); -} - -// Path: tags -class _TranslationsTagsEs implements TranslationsTagsEn { - _TranslationsTagsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get tags => 'Etiquetas'; - @override String created({required Object created}) => 'Creado: ${created}'; - @override late final _TranslationsTagsCreateTagEs createTag = _TranslationsTagsCreateTagEs._(_root); - @override late final _TranslationsTagsFilteredBookmarksEs filteredBookmarks = _TranslationsTagsFilteredBookmarksEs._(_root); -} - -// Path: settings -class _TranslationsSettingsEs implements TranslationsSettingsEn { - _TranslationsSettingsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get settings => 'Ajustes'; - @override String get appSettings => 'Ajustes de la aplicación'; - @override String get aboutApp => 'Sobre la aplicación'; - @override String get appVersion => 'Versión de la aplicación'; - @override String get createdBy => 'Creado por'; - @override String get visitGooglePlay => 'Visita la página de la aplicación en Google Play'; - @override String get visitGitHubRepo => 'Visita el repositorio de la aplicación en GitHub'; - @override String get linkdingRepository => 'Repositorio de Linkding'; - @override String get linkdingRepositoryDescription => 'Enlace al repositorio de Linkding en GitHub'; - @override String get moreInfoApp => 'Más información sobre la aplicación'; - @override String get moreInfoAppDescription => 'Enlace a la página web de información de la aplicación'; - @override String get moreApps => 'Mis otras aplicaciones'; - @override String get moreAppsDescription => 'Más aplicaciones, contacto, donaciones y más'; - @override String get selectAnOption => 'Selecciona una opción'; - @override late final _TranslationsSettingsCustomizationEs customization = _TranslationsSettingsCustomizationEs._(_root); - @override late final _TranslationsSettingsGeneralSettingsEs generalSettings = _TranslationsSettingsGeneralSettingsEs._(_root); -} - -// Path: webview -class _TranslationsWebviewEs implements TranslationsWebviewEn { - _TranslationsWebviewEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get goBack => 'Ir atrás'; - @override String get goForward => 'Ir adelante'; - @override String get reload => 'Recargar'; - @override String get openInSystemBrowser => 'Abrir en el navegador del sistema'; - @override String get copyLinkClipboard => 'Copiar enlace al portapapeles'; - @override String get linkCopiedClipboard => 'Enlace copiado al portapapeles.'; - @override String get share => 'Compartir'; - @override String get invalidBookmarkData => 'El marcador tiene datos inválidos o está corrupto.'; -} - -// Path: colors -class _TranslationsColorsEs implements TranslationsColorsEn { - _TranslationsColorsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get red => 'Rojo'; - @override String get green => 'Verde'; - @override String get blue => 'Azul'; - @override String get yellow => 'Amarillo'; - @override String get orange => 'Naranja'; - @override String get brown => 'Marron'; - @override String get cyan => 'Cian'; - @override String get purple => 'Morado'; - @override String get pink => 'Rosa'; - @override String get deepOrange => 'Naranja oscuro'; - @override String get indigo => 'Índigo'; -} - -// Path: bookmarks.dates -class _TranslationsBookmarksDatesEs implements TranslationsBookmarksDatesEn { - _TranslationsBookmarksDatesEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String todayAt({required Object time}) => 'Hoy, ${time}'; - @override String yesterdayAt({required Object time}) => 'Ayer, ${time}'; -} - -// Path: bookmarks.addBookmark -class _TranslationsBookmarksAddBookmarkEs implements TranslationsBookmarksAddBookmarkEn { - _TranslationsBookmarksAddBookmarkEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get addBookmark => 'Añadir nuevo marcador'; - @override String get editBookmark => 'Editar marcador'; - @override String get url => 'URL'; - @override String get bookmarkUrl => 'URL del marcador'; - @override String get bookmarkDetails => 'Detalles del marcador'; - @override String get validateUrl => 'Validar URL'; - @override String get urlValid => 'La URL es válida'; - @override String get urlNotValid => 'La URL no es válida'; - @override String get cannotCheckUrl => 'No se pudo comprobar la URL, pero puedes guardarla de todas formas.'; - @override String get invalidUrl => 'URL no válida'; - @override String get checkingUrl => 'Comprobando URL...'; - @override String get title => 'Title'; - @override String get description => 'Description'; - @override String get markAsUnread => 'Marcar como no leído'; - @override String get markAsUnreadDescription => 'Los marcadores no leídos pueden filtrarse y marcarse como leídos después de haberlos consultado.'; - @override String get notes => 'Notas'; - @override String get addNotes => 'Añadir notas'; - @override String get tags => 'Etiquetas'; - @override String get noTagsAdded => 'No hay etiquetas añadidas'; - @override String get tagNoWhitespaces => 'La etiqueta no puede contener espacios'; - @override String get addTag => 'Añadir etiqueta'; - @override String get others => 'Otros'; - @override String get savingBookmark => 'Guardando marcador...'; - @override String get bookmarkSavedSuccessfully => 'Marcador guardado correctamente'; - @override String get errorSavingBookmark => 'Ocurrió un error al guardar el nuevo marcador.'; - @override String get leaveEmptyUseWebsiteTitle => 'Dejar vacío para usar el título del sitio web.'; - @override String get leaveEmptyUseWebsiteDescription => 'Dejar vacío para usar la descripción del sitio web.'; - @override String get share => 'Compartir'; - @override String get shareDescription => 'Comparte este marcador con otros usuarios registrados y usuarios anónimos.'; - @override String get urlAlreadyBookmarked => 'Esta URL ya está marcada como favorita. El formulario se ha rellenado previamente con el marcador existente, y al guardar el formulario se actualizará el marcador existente.'; -} - -// Path: bookmarks.search -class _TranslationsBookmarksSearchEs implements TranslationsBookmarksSearchEn { - _TranslationsBookmarksSearchEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get searchBookmarks => 'Buscar marcadores'; - @override String get clearSearch => 'Limpiar búsqueda'; - @override String get inputSearchTerm => 'Introduce un término de búsqueda'; - @override String get cannotSearchError => 'No se puede buscar el contenido por un error'; - @override String get inputtedSearchTermNoResults => 'El término de búsqueda introducido no tiene resultados'; -} - -// Path: bookmarks.bookmarkOptions -class _TranslationsBookmarksBookmarkOptionsEs implements TranslationsBookmarksBookmarkOptionsEn { - _TranslationsBookmarksBookmarkOptionsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get edit => 'Editar'; - @override String get delete => 'Eliminar'; - @override String get read => 'Leído'; - @override String get unread => 'No leído'; - @override String get markAsUnread => 'Marcar como no leído'; - @override String get markAsRead => 'Marcar como leído'; - @override String get shareOptions => 'Opciones de compartir'; - @override String get shared => 'Compartido'; - @override String get archive => 'Archivar'; - @override String get unarchive => 'Desarchivar'; - @override String get deletingBookmark => 'Eliminando marcador...'; - @override String get bookmarkDeleted => 'Marcador eliminado correctamente'; - @override String get bookmarkNotDeleted => 'El marcador no se ha podido eliminar debido a un error.'; - @override String get deleteBookmark => 'Eliminar marcador'; - @override String get followingBookmarkDeleted => 'El siguiente marcador será eliminado:'; - @override String get markingAsRead => 'Marcando como leído...'; - @override String get markingAsUnead => 'Marcando como no leído...'; - @override String get markedAsReadSuccessfully => 'Marcador marcado como leído correctamente.'; - @override String get markedAsUnreadSuccessfully => 'Marcador marcado como no leído correctamente.'; - @override String get bookmarkNotMarkedAsRead => 'El marcador no se ha podido marcar como leído.'; - @override String get bookmarkNotMarkedAsUnread => 'El marcador no se ha podido marcar como no leído.'; - @override String get archivingBookmark => 'Archivando marcador...'; - @override String get unarchivingBookmark => 'Desarchivando marcador...'; - @override String get bookmarkArchivedSuccessfully => 'Marcador archivado correctamente.'; - @override String get bookmarkUnrchivedSuccessfully => 'Marcador desarchivado correctamente.'; - @override String get bookmarkNotArchived => 'El marcador no pudo ser archivado.'; - @override String get bookmarkNotUnrchived => 'El marcador no pudo ser desarchivado.'; - @override String get shareThirdPartyApp => 'Compartir usando una app de terceros'; - @override String get shareInternally => 'Compartir internamente'; - @override String get unshareInternally => 'Descompartir internamente'; -} - -// Path: bookmarks.shareOptions -class _TranslationsBookmarksShareOptionsEs implements TranslationsBookmarksShareOptionsEn { - _TranslationsBookmarksShareOptionsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get shareOptions => 'Opciones de compartir'; - @override String get shareInternally => 'Compartir internamente'; - @override String get unshareInternally => 'Descompartir internamente'; - @override String get shareInternallyDescription => 'Compartir internamente con el resto de usuarios de la instancia de Linkding'; - @override String get unshareInternallyDescription => 'Descompartir el marcador compartido internamente'; - @override String get shareExternally => 'Compartir URL del marcador externamente'; - @override String get shareExternallyDescription => 'Compartir la URL del marcador externamente usando una aplicación de terceros'; - @override String get sharingBookmark => 'Compartiendo marcador...'; - @override String get unsharingBookmark => 'Descompartiendo marcador...'; - @override String get bookmarkSharedSuccessfully => 'Marcador compartido correctamente.'; - @override String get bookmarkNotShared => 'El marcador no pudo ser compartido.'; - @override String get bookmarkUnsharedSuccessfully => 'Marcador descompartido correctamente.'; - @override String get bookmarkNotUnshared => 'El marcador no pudo ser descompartido.'; -} - -// Path: tags.createTag -class _TranslationsTagsCreateTagEs implements TranslationsTagsCreateTagEn { - _TranslationsTagsCreateTagEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get createTag => 'Crear etiqueta'; - @override String get name => 'Nombre'; - @override String get creatingTag => 'Creando etiqueta...'; - @override String get errorCreatingTag => 'Ocurrió un error al crear la etiqueta.'; -} - -// Path: tags.filteredBookmarks -class _TranslationsTagsFilteredBookmarksEs implements TranslationsTagsFilteredBookmarksEn { - _TranslationsTagsFilteredBookmarksEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get noBookmarksWithThisTag => 'No hay marcadores con esta etiqueta'; - @override String get noArchivedBookmarks => 'No hay marcadores archivados'; - @override String get noSharedBookmarks => 'No hay marcadores compartidos'; -} - -// Path: settings.customization -class _TranslationsSettingsCustomizationEs implements TranslationsSettingsCustomizationEn { - _TranslationsSettingsCustomizationEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get customization => 'Personalización'; - @override String get customizationDescription => 'Configura el tema y la paleta de colores.'; - @override String get theme => 'Tema'; - @override String get light => 'Claro'; - @override String get dark => 'Oscuro'; - @override String get systemDefined => 'Definido por el sistema'; - @override String get color => 'Color'; - @override String get useDynamicTheme => 'Usar tema dinámico'; -} - -// Path: settings.generalSettings -class _TranslationsSettingsGeneralSettingsEs implements TranslationsSettingsGeneralSettingsEn { - _TranslationsSettingsGeneralSettingsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get generalSettings => 'Ajustes generales'; - @override String get generalSettingsDescription => 'Ajustes generales para la aplicación.'; - @override String get bookmarks => 'Marcadores'; - @override String get showFavicon => 'Mostrar favicon'; - @override String get showFaviconDescription => 'Mostrar el favicon del sitio web en cada marcador.'; - @override String get disconnectFromServer => 'Desconectar del servidor'; - @override late final _TranslationsSettingsGeneralSettingsDisconnectModalEs disconnectModal = _TranslationsSettingsGeneralSettingsDisconnectModalEs._(_root); - @override String get useInAppBrowser => 'Usar navegador de la aplicación'; - @override String get useInAppBrowserDescription => 'Abre los marcadores con el navegador integrado en vez de con el navegador del sietema. En modo tablet siempre se usará el navegador integrado.'; - @override String get openLinksWith => 'Abrir enlaces con...'; - @override String get internalBrowser => 'Navegador interno de la app'; - @override String get browserCustomTab => 'Pestaña personalizada del navegador'; - @override String get systemBrowser => 'Navegador del sistema'; - @override String get tags => 'Etiquetas'; - @override late final _TranslationsSettingsGeneralSettingsDefaultTagsEs defaultTags = _TranslationsSettingsGeneralSettingsDefaultTagsEs._(_root); - @override String get others => 'Otros'; - @override String get setMarkAsUnreadDefault => 'Marcar como no leído por defecto'; - @override String get setMarkAsUnreadDefaultDescription => 'Habilitar por defecto la opción de marcar como leído al crear un marcador.'; - @override String get enableSlideOptions => 'Habilitar opciones al deslizar'; - @override String get enableSlideOptionsDescription => 'Habilitar opciones al deslizar en la lista de marcadores'; -} - -// Path: settings.generalSettings.disconnectModal -class _TranslationsSettingsGeneralSettingsDisconnectModalEs implements TranslationsSettingsGeneralSettingsDisconnectModalEn { - _TranslationsSettingsGeneralSettingsDisconnectModalEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get title => 'Desconectar'; - @override String get description => '¿Estás seguro que deseas desconectarte del servidor?\nSerás redirigido a la configuración inicial.'; -} - -// Path: settings.generalSettings.defaultTags -class _TranslationsSettingsGeneralSettingsDefaultTagsEs implements TranslationsSettingsGeneralSettingsDefaultTagsEn { - _TranslationsSettingsGeneralSettingsDefaultTagsEs._(this._root); - - final TranslationsEs _root; // ignore: unused_field - - // Translations - @override String get defaultTags => 'Etiquetas por defecto'; - @override String get defaultTagsDescription => 'Define una lista de etiquetas que se añadirán por defecto al crear un marcador'; - @override String get newTag => 'Nueva etiqueta'; - @override String get addTag => 'Añadir etiqueta'; - @override String get removeThisTag => 'Eliminar esta etiqueta'; - @override String get noDefaultTags => 'No hay etiquetas por defecto'; -} - -/// The flat map containing all translations for locale . -/// Only for edge cases! For simple maps, use the map function of this library. -/// -/// The Dart AOT compiler has issues with very large switch statements, -/// so the map is split into smaller functions (512 entries each). -extension on TranslationsEs { - dynamic _flatMapFunction(String path) { - return switch (path) { - 'generic.confirm' => 'Confirmar', - 'generic.cancel' => 'Cancelar', - 'generic.next' => 'Siguiente', - 'generic.save' => 'Guardar', - 'generic.close' => 'Cerrar', - 'generic.error' => 'Error', - 'generic.optional' => 'Opcional', - 'generic.authTokenNotValid' => 'Su token de autorización ya no es válido. Por favor, vuelva a autenticarse.', - 'generic.options' => 'Opciones', - 'onboarding.title' => 'Bienvenido a Linkdy', - 'onboarding.subtitle' => 'Una aplicación para gestionar tus enlaces favoritos.', - 'onboarding.start' => 'Comenzar', - 'onboarding.next' => 'Siguiente', - 'onboarding.previous' => 'Anterior', - 'onboarding.serverRequired' => 'Servidor requerido', - 'onboarding.serverRequiredDescription' => 'Linkdy no es una aplicación independiente, requiere el servidor Linkding para funcionar.\nPara utilizar esta aplicación, debe instalar Linkding en su servidor doméstico, VPS o cualquier otro ordenador.', - 'onboarding.installationInstructions' => 'Mira las instrucciones de instalación en el repositorio oficial en GitHub.', - 'onboarding.serverRunningConfirmation' => 'Confirmo que tengo una instancia del servidor Linkding ya en funcionamiento.', - 'onboarding.createConnection' => 'Crear una conexión', - 'onboarding.createConnectionSubtitle' => 'Introduce todos los detalles requeridos para crear una conexión con el servidor', - 'onboarding.ipAddressOrDomain' => 'Dirección IP o dominio', - 'onboarding.port' => 'Puerto', - 'onboarding.path' => 'Ruta', - 'onboarding.invalidPath' => 'Ruta no válida', - 'onboarding.token' => 'Token', - 'onboarding.required' => 'Requerido', - 'onboarding.serverDetails' => 'Detalles del servidor', - 'onboarding.authentication' => 'Autenticación', - 'onboarding.testConnectionUrl' => 'Probar URL de conexión', - 'onboarding.testingConnection' => 'Probando conexión...', - 'onboarding.connectionServerEstablished' => 'Conexión con servidor establecida', - 'onboarding.connectionServerFailed' => 'Conexión con servidor fallida', - 'onboarding.connect' => 'Conectar', - 'onboarding.connecting' => 'Conectando...', - 'onboarding.cannotConnectToServer' => 'No se puede conectar con el servidor.', - 'onboarding.invalidToken' => 'Token no válido.', - 'onboarding.invalidIpDomain' => 'Dirección IP o dominio no válido', - 'onboarding.invalidPort' => 'Puerto no válido', - 'onboarding.tokenRequired' => 'Token requerido', - 'bookmarks.bookmarks' => 'Marcadores', - 'bookmarks.noBookmarksAdded' => 'No hay marcadores añadidos', - 'bookmarks.cannotLoadBookmarks' => 'No se pueden cargar los marcadores', - 'bookmarks.dates.todayAt' => ({required Object time}) => 'Hoy, ${time}', - 'bookmarks.dates.yesterdayAt' => ({required Object time}) => 'Ayer, ${time}', - 'bookmarks.shared' => 'Compartidos', - 'bookmarks.archived' => 'Archivados', - 'bookmarks.showOnlyRead' => 'Mostrar solo leídos', - 'bookmarks.showOnlyUnread' => 'Mostrar solo no leídos', - 'bookmarks.showAllBookmarks' => 'Mostrar todos los marcadores', - 'bookmarks.readStatus' => 'Estado de lectura', - 'bookmarks.all' => 'Todos', - 'bookmarks.unread' => 'No leídos', - 'bookmarks.read' => 'Leídos', - 'bookmarks.filterSort' => 'Filtrar y ordenar', - 'bookmarks.sorting' => 'Ordenación', - 'bookmarks.date' => 'Fecha', - 'bookmarks.title' => 'Título', - 'bookmarks.ascendant' => 'Ascendiente', - 'bookmarks.descendant' => 'Descendiente', - 'bookmarks.addBookmark.addBookmark' => 'Añadir nuevo marcador', - 'bookmarks.addBookmark.editBookmark' => 'Editar marcador', - 'bookmarks.addBookmark.url' => 'URL', - 'bookmarks.addBookmark.bookmarkUrl' => 'URL del marcador', - 'bookmarks.addBookmark.bookmarkDetails' => 'Detalles del marcador', - 'bookmarks.addBookmark.validateUrl' => 'Validar URL', - 'bookmarks.addBookmark.urlValid' => 'La URL es válida', - 'bookmarks.addBookmark.urlNotValid' => 'La URL no es válida', - 'bookmarks.addBookmark.cannotCheckUrl' => 'No se pudo comprobar la URL, pero puedes guardarla de todas formas.', - 'bookmarks.addBookmark.invalidUrl' => 'URL no válida', - 'bookmarks.addBookmark.checkingUrl' => 'Comprobando URL...', - 'bookmarks.addBookmark.title' => 'Title', - 'bookmarks.addBookmark.description' => 'Description', - 'bookmarks.addBookmark.markAsUnread' => 'Marcar como no leído', - 'bookmarks.addBookmark.markAsUnreadDescription' => 'Los marcadores no leídos pueden filtrarse y marcarse como leídos después de haberlos consultado.', - 'bookmarks.addBookmark.notes' => 'Notas', - 'bookmarks.addBookmark.addNotes' => 'Añadir notas', - 'bookmarks.addBookmark.tags' => 'Etiquetas', - 'bookmarks.addBookmark.noTagsAdded' => 'No hay etiquetas añadidas', - 'bookmarks.addBookmark.tagNoWhitespaces' => 'La etiqueta no puede contener espacios', - 'bookmarks.addBookmark.addTag' => 'Añadir etiqueta', - 'bookmarks.addBookmark.others' => 'Otros', - 'bookmarks.addBookmark.savingBookmark' => 'Guardando marcador...', - 'bookmarks.addBookmark.bookmarkSavedSuccessfully' => 'Marcador guardado correctamente', - 'bookmarks.addBookmark.errorSavingBookmark' => 'Ocurrió un error al guardar el nuevo marcador.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteTitle' => 'Dejar vacío para usar el título del sitio web.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteDescription' => 'Dejar vacío para usar la descripción del sitio web.', - 'bookmarks.addBookmark.share' => 'Compartir', - 'bookmarks.addBookmark.shareDescription' => 'Comparte este marcador con otros usuarios registrados y usuarios anónimos.', - 'bookmarks.addBookmark.urlAlreadyBookmarked' => 'Esta URL ya está marcada como favorita. El formulario se ha rellenado previamente con el marcador existente, y al guardar el formulario se actualizará el marcador existente.', - 'bookmarks.search.searchBookmarks' => 'Buscar marcadores', - 'bookmarks.search.clearSearch' => 'Limpiar búsqueda', - 'bookmarks.search.inputSearchTerm' => 'Introduce un término de búsqueda', - 'bookmarks.search.cannotSearchError' => 'No se puede buscar el contenido por un error', - 'bookmarks.search.inputtedSearchTermNoResults' => 'El término de búsqueda introducido no tiene resultados', - 'bookmarks.bookmarkOptions.edit' => 'Editar', - 'bookmarks.bookmarkOptions.delete' => 'Eliminar', - 'bookmarks.bookmarkOptions.read' => 'Leído', - 'bookmarks.bookmarkOptions.unread' => 'No leído', - 'bookmarks.bookmarkOptions.markAsUnread' => 'Marcar como no leído', - 'bookmarks.bookmarkOptions.markAsRead' => 'Marcar como leído', - 'bookmarks.bookmarkOptions.shareOptions' => 'Opciones de compartir', - 'bookmarks.bookmarkOptions.shared' => 'Compartido', - 'bookmarks.bookmarkOptions.archive' => 'Archivar', - 'bookmarks.bookmarkOptions.unarchive' => 'Desarchivar', - 'bookmarks.bookmarkOptions.deletingBookmark' => 'Eliminando marcador...', - 'bookmarks.bookmarkOptions.bookmarkDeleted' => 'Marcador eliminado correctamente', - 'bookmarks.bookmarkOptions.bookmarkNotDeleted' => 'El marcador no se ha podido eliminar debido a un error.', - 'bookmarks.bookmarkOptions.deleteBookmark' => 'Eliminar marcador', - 'bookmarks.bookmarkOptions.followingBookmarkDeleted' => 'El siguiente marcador será eliminado:', - 'bookmarks.bookmarkOptions.markingAsRead' => 'Marcando como leído...', - 'bookmarks.bookmarkOptions.markingAsUnead' => 'Marcando como no leído...', - 'bookmarks.bookmarkOptions.markedAsReadSuccessfully' => 'Marcador marcado como leído correctamente.', - 'bookmarks.bookmarkOptions.markedAsUnreadSuccessfully' => 'Marcador marcado como no leído correctamente.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead' => 'El marcador no se ha podido marcar como leído.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread' => 'El marcador no se ha podido marcar como no leído.', - 'bookmarks.bookmarkOptions.archivingBookmark' => 'Archivando marcador...', - 'bookmarks.bookmarkOptions.unarchivingBookmark' => 'Desarchivando marcador...', - 'bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully' => 'Marcador archivado correctamente.', - 'bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully' => 'Marcador desarchivado correctamente.', - 'bookmarks.bookmarkOptions.bookmarkNotArchived' => 'El marcador no pudo ser archivado.', - 'bookmarks.bookmarkOptions.bookmarkNotUnrchived' => 'El marcador no pudo ser desarchivado.', - 'bookmarks.bookmarkOptions.shareThirdPartyApp' => 'Compartir usando una app de terceros', - 'bookmarks.bookmarkOptions.shareInternally' => 'Compartir internamente', - 'bookmarks.bookmarkOptions.unshareInternally' => 'Descompartir internamente', - 'bookmarks.shareOptions.shareOptions' => 'Opciones de compartir', - 'bookmarks.shareOptions.shareInternally' => 'Compartir internamente', - 'bookmarks.shareOptions.unshareInternally' => 'Descompartir internamente', - 'bookmarks.shareOptions.shareInternallyDescription' => 'Compartir internamente con el resto de usuarios de la instancia de Linkding', - 'bookmarks.shareOptions.unshareInternallyDescription' => 'Descompartir el marcador compartido internamente', - 'bookmarks.shareOptions.shareExternally' => 'Compartir URL del marcador externamente', - 'bookmarks.shareOptions.shareExternallyDescription' => 'Compartir la URL del marcador externamente usando una aplicación de terceros', - 'bookmarks.shareOptions.sharingBookmark' => 'Compartiendo marcador...', - 'bookmarks.shareOptions.unsharingBookmark' => 'Descompartiendo marcador...', - 'bookmarks.shareOptions.bookmarkSharedSuccessfully' => 'Marcador compartido correctamente.', - 'bookmarks.shareOptions.bookmarkNotShared' => 'El marcador no pudo ser compartido.', - 'bookmarks.shareOptions.bookmarkUnsharedSuccessfully' => 'Marcador descompartido correctamente.', - 'bookmarks.shareOptions.bookmarkNotUnshared' => 'El marcador no pudo ser descompartido.', - 'tags.tags' => 'Etiquetas', - 'tags.created' => ({required Object created}) => 'Creado: ${created}', - 'tags.createTag.createTag' => 'Crear etiqueta', - 'tags.createTag.name' => 'Nombre', - 'tags.createTag.creatingTag' => 'Creando etiqueta...', - 'tags.createTag.errorCreatingTag' => 'Ocurrió un error al crear la etiqueta.', - 'tags.filteredBookmarks.noBookmarksWithThisTag' => 'No hay marcadores con esta etiqueta', - 'tags.filteredBookmarks.noArchivedBookmarks' => 'No hay marcadores archivados', - 'tags.filteredBookmarks.noSharedBookmarks' => 'No hay marcadores compartidos', - 'settings.settings' => 'Ajustes', - 'settings.appSettings' => 'Ajustes de la aplicación', - 'settings.aboutApp' => 'Sobre la aplicación', - 'settings.appVersion' => 'Versión de la aplicación', - 'settings.createdBy' => 'Creado por', - 'settings.visitGooglePlay' => 'Visita la página de la aplicación en Google Play', - 'settings.visitGitHubRepo' => 'Visita el repositorio de la aplicación en GitHub', - 'settings.linkdingRepository' => 'Repositorio de Linkding', - 'settings.linkdingRepositoryDescription' => 'Enlace al repositorio de Linkding en GitHub', - 'settings.moreInfoApp' => 'Más información sobre la aplicación', - 'settings.moreInfoAppDescription' => 'Enlace a la página web de información de la aplicación', - 'settings.moreApps' => 'Mis otras aplicaciones', - 'settings.moreAppsDescription' => 'Más aplicaciones, contacto, donaciones y más', - 'settings.selectAnOption' => 'Selecciona una opción', - 'settings.customization.customization' => 'Personalización', - 'settings.customization.customizationDescription' => 'Configura el tema y la paleta de colores.', - 'settings.customization.theme' => 'Tema', - 'settings.customization.light' => 'Claro', - 'settings.customization.dark' => 'Oscuro', - 'settings.customization.systemDefined' => 'Definido por el sistema', - 'settings.customization.color' => 'Color', - 'settings.customization.useDynamicTheme' => 'Usar tema dinámico', - 'settings.generalSettings.generalSettings' => 'Ajustes generales', - 'settings.generalSettings.generalSettingsDescription' => 'Ajustes generales para la aplicación.', - 'settings.generalSettings.bookmarks' => 'Marcadores', - 'settings.generalSettings.showFavicon' => 'Mostrar favicon', - 'settings.generalSettings.showFaviconDescription' => 'Mostrar el favicon del sitio web en cada marcador.', - 'settings.generalSettings.disconnectFromServer' => 'Desconectar del servidor', - 'settings.generalSettings.disconnectModal.title' => 'Desconectar', - 'settings.generalSettings.disconnectModal.description' => '¿Estás seguro que deseas desconectarte del servidor?\nSerás redirigido a la configuración inicial.', - 'settings.generalSettings.useInAppBrowser' => 'Usar navegador de la aplicación', - 'settings.generalSettings.useInAppBrowserDescription' => 'Abre los marcadores con el navegador integrado en vez de con el navegador del sietema. En modo tablet siempre se usará el navegador integrado.', - 'settings.generalSettings.openLinksWith' => 'Abrir enlaces con...', - 'settings.generalSettings.internalBrowser' => 'Navegador interno de la app', - 'settings.generalSettings.browserCustomTab' => 'Pestaña personalizada del navegador', - 'settings.generalSettings.systemBrowser' => 'Navegador del sistema', - 'settings.generalSettings.tags' => 'Etiquetas', - 'settings.generalSettings.defaultTags.defaultTags' => 'Etiquetas por defecto', - 'settings.generalSettings.defaultTags.defaultTagsDescription' => 'Define una lista de etiquetas que se añadirán por defecto al crear un marcador', - 'settings.generalSettings.defaultTags.newTag' => 'Nueva etiqueta', - 'settings.generalSettings.defaultTags.addTag' => 'Añadir etiqueta', - 'settings.generalSettings.defaultTags.removeThisTag' => 'Eliminar esta etiqueta', - 'settings.generalSettings.defaultTags.noDefaultTags' => 'No hay etiquetas por defecto', - 'settings.generalSettings.others' => 'Otros', - 'settings.generalSettings.setMarkAsUnreadDefault' => 'Marcar como no leído por defecto', - 'settings.generalSettings.setMarkAsUnreadDefaultDescription' => 'Habilitar por defecto la opción de marcar como leído al crear un marcador.', - 'settings.generalSettings.enableSlideOptions' => 'Habilitar opciones al deslizar', - 'settings.generalSettings.enableSlideOptionsDescription' => 'Habilitar opciones al deslizar en la lista de marcadores', - 'webview.goBack' => 'Ir atrás', - 'webview.goForward' => 'Ir adelante', - 'webview.reload' => 'Recargar', - 'webview.openInSystemBrowser' => 'Abrir en el navegador del sistema', - 'webview.copyLinkClipboard' => 'Copiar enlace al portapapeles', - 'webview.linkCopiedClipboard' => 'Enlace copiado al portapapeles.', - 'webview.share' => 'Compartir', - 'webview.invalidBookmarkData' => 'El marcador tiene datos inválidos o está corrupto.', - 'colors.red' => 'Rojo', - 'colors.green' => 'Verde', - 'colors.blue' => 'Azul', - 'colors.yellow' => 'Amarillo', - 'colors.orange' => 'Naranja', - 'colors.brown' => 'Marron', - 'colors.cyan' => 'Cian', - 'colors.purple' => 'Morado', - 'colors.pink' => 'Rosa', - 'colors.deepOrange' => 'Naranja oscuro', - 'colors.indigo' => 'Índigo', - _ => null, - }; - } -} diff --git a/lib/i18n/strings_es.i18n.json b/lib/i18n/strings_es.i18n.json deleted file mode 100644 index f930b35..0000000 --- a/lib/i18n/strings_es.i18n.json +++ /dev/null @@ -1,251 +0,0 @@ -{ - "generic": { - "confirm": "Confirmar", - "cancel": "Cancelar", - "next": "Siguiente", - "save": "Guardar", - "close": "Cerrar", - "error": "Error", - "optional": "Opcional", - "authTokenNotValid": "Su token de autorización ya no es válido. Por favor, vuelva a autenticarse.", - "options": "Opciones" - }, - "onboarding": { - "title": "Bienvenido a Linkdy", - "subtitle": "Una aplicación para gestionar tus enlaces favoritos.", - "start": "Comenzar", - "next": "Siguiente", - "previous": "Anterior", - "serverRequired": "Servidor requerido", - "serverRequiredDescription": "Linkdy no es una aplicación independiente, requiere el servidor Linkding para funcionar.\nPara utilizar esta aplicación, debe instalar Linkding en su servidor doméstico, VPS o cualquier otro ordenador.", - "installationInstructions": "Mira las instrucciones de instalación en el repositorio oficial en GitHub.", - "serverRunningConfirmation": "Confirmo que tengo una instancia del servidor Linkding ya en funcionamiento.", - "createConnection": "Crear una conexión", - "createConnectionSubtitle": "Introduce todos los detalles requeridos para crear una conexión con el servidor", - "ipAddressOrDomain": "Dirección IP o dominio", - "port": "Puerto", - "path": "Ruta", - "invalidPath": "Ruta no válida", - "token": "Token", - "required": "Requerido", - "serverDetails": "Detalles del servidor", - "authentication": "Autenticación", - "testConnectionUrl": "Probar URL de conexión", - "testingConnection": "Probando conexión...", - "connectionServerEstablished": "Conexión con servidor establecida", - "connectionServerFailed": "Conexión con servidor fallida", - "connect": "Conectar", - "connecting": "Conectando...", - "cannotConnectToServer": "No se puede conectar con el servidor.", - "invalidToken": "Token no válido.", - "invalidIpDomain": "Dirección IP o dominio no válido", - "invalidPort": "Puerto no válido", - "tokenRequired": "Token requerido" - }, - "bookmarks": { - "bookmarks": "Marcadores", - "noBookmarksAdded": "No hay marcadores añadidos", - "cannotLoadBookmarks": "No se pueden cargar los marcadores", - "dates": { - "todayAt": "Hoy, $time", - "yesterdayAt": "Ayer, $time" - }, - "shared": "Compartidos", - "archived": "Archivados", - "showOnlyRead": "Mostrar solo leídos", - "showOnlyUnread": "Mostrar solo no leídos", - "showAllBookmarks": "Mostrar todos los marcadores", - "readStatus": "Estado de lectura", - "all": "Todos", - "unread": "No leídos", - "read": "Leídos", - "filterSort": "Filtrar y ordenar", - "sorting": "Ordenación", - "date": "Fecha", - "title": "Título", - "ascendant": "Ascendiente", - "descendant": "Descendiente", - "addBookmark": { - "addBookmark": "Añadir nuevo marcador", - "editBookmark": "Editar marcador", - "url": "URL", - "bookmarkUrl": "URL del marcador", - "bookmarkDetails": "Detalles del marcador", - "validateUrl": "Validar URL", - "urlValid": "La URL es válida", - "urlNotValid": "La URL no es válida", - "cannotCheckUrl": "No se pudo comprobar la URL, pero puedes guardarla de todas formas.", - "invalidUrl": "URL no válida", - "checkingUrl": "Comprobando URL...", - "title": "Title", - "description": "Description", - "markAsUnread": "Marcar como no leído", - "markAsUnreadDescription": "Los marcadores no leídos pueden filtrarse y marcarse como leídos después de haberlos consultado.", - "notes": "Notas", - "addNotes": "Añadir notas", - "tags": "Etiquetas", - "noTagsAdded": "No hay etiquetas añadidas", - "tagNoWhitespaces": "La etiqueta no puede contener espacios", - "addTag": "Añadir etiqueta", - "others": "Otros", - "savingBookmark": "Guardando marcador...", - "bookmarkSavedSuccessfully": "Marcador guardado correctamente", - "errorSavingBookmark": "Ocurrió un error al guardar el nuevo marcador.", - "leaveEmptyUseWebsiteTitle": "Dejar vacío para usar el título del sitio web.", - "leaveEmptyUseWebsiteDescription": "Dejar vacío para usar la descripción del sitio web.", - "share": "Compartir", - "shareDescription": "Comparte este marcador con otros usuarios registrados y usuarios anónimos.", - "urlAlreadyBookmarked": "Esta URL ya está marcada como favorita. El formulario se ha rellenado previamente con el marcador existente, y al guardar el formulario se actualizará el marcador existente." - }, - "search": { - "searchBookmarks": "Buscar marcadores", - "clearSearch": "Limpiar búsqueda", - "inputSearchTerm": "Introduce un término de búsqueda", - "cannotSearchError": "No se puede buscar el contenido por un error", - "inputtedSearchTermNoResults": "El término de búsqueda introducido no tiene resultados" - }, - "bookmarkOptions": { - "edit": "Editar", - "delete": "Eliminar", - "read": "Leído", - "unread": "No leído", - "markAsUnread": "Marcar como no leído", - "markAsRead": "Marcar como leído", - "shareOptions": "Opciones de compartir", - "shared": "Compartido", - "archive": "Archivar", - "unarchive": "Desarchivar", - "deletingBookmark": "Eliminando marcador...", - "bookmarkDeleted": "Marcador eliminado correctamente", - "bookmarkNotDeleted": "El marcador no se ha podido eliminar debido a un error.", - "deleteBookmark": "Eliminar marcador", - "followingBookmarkDeleted": "El siguiente marcador será eliminado:", - "markingAsRead": "Marcando como leído...", - "markingAsUnead": "Marcando como no leído...", - "markedAsReadSuccessfully": "Marcador marcado como leído correctamente.", - "markedAsUnreadSuccessfully": "Marcador marcado como no leído correctamente.", - "bookmarkNotMarkedAsRead": "El marcador no se ha podido marcar como leído.", - "bookmarkNotMarkedAsUnread": "El marcador no se ha podido marcar como no leído.", - "archivingBookmark": "Archivando marcador...", - "unarchivingBookmark": "Desarchivando marcador...", - "bookmarkArchivedSuccessfully": "Marcador archivado correctamente.", - "bookmarkUnrchivedSuccessfully": "Marcador desarchivado correctamente.", - "bookmarkNotArchived": "El marcador no pudo ser archivado.", - "bookmarkNotUnrchived": "El marcador no pudo ser desarchivado.", - "shareThirdPartyApp": "Compartir usando una app de terceros", - "shareInternally": "Compartir internamente", - "unshareInternally": "Descompartir internamente" - }, - "shareOptions": { - "shareOptions": "Opciones de compartir", - "shareInternally": "Compartir internamente", - "unshareInternally": "Descompartir internamente", - "shareInternallyDescription": "Compartir internamente con el resto de usuarios de la instancia de Linkding", - "unshareInternallyDescription": "Descompartir el marcador compartido internamente", - "shareExternally": "Compartir URL del marcador externamente", - "shareExternallyDescription": "Compartir la URL del marcador externamente usando una aplicación de terceros", - "sharingBookmark": "Compartiendo marcador...", - "unsharingBookmark": "Descompartiendo marcador...", - "bookmarkSharedSuccessfully": "Marcador compartido correctamente.", - "bookmarkNotShared": "El marcador no pudo ser compartido.", - "bookmarkUnsharedSuccessfully": "Marcador descompartido correctamente.", - "bookmarkNotUnshared": "El marcador no pudo ser descompartido." - } - }, - "tags": { - "tags": "Etiquetas", - "created": "Creado: $created", - "createTag": { - "createTag": "Crear etiqueta", - "name": "Nombre", - "creatingTag": "Creando etiqueta...", - "errorCreatingTag": "Ocurrió un error al crear la etiqueta." - }, - "filteredBookmarks": { - "noBookmarksWithThisTag": "No hay marcadores con esta etiqueta", - "noArchivedBookmarks": "No hay marcadores archivados", - "noSharedBookmarks": "No hay marcadores compartidos" - } - }, - "settings": { - "settings": "Ajustes", - "appSettings": "Ajustes de la aplicación", - "aboutApp": "Sobre la aplicación", - "appVersion": "Versión de la aplicación", - "createdBy": "Creado por", - "visitGooglePlay": "Visita la página de la aplicación en Google Play", - "visitGitHubRepo": "Visita el repositorio de la aplicación en GitHub", - "linkdingRepository": "Repositorio de Linkding", - "linkdingRepositoryDescription": "Enlace al repositorio de Linkding en GitHub", - "moreInfoApp": "Más información sobre la aplicación", - "moreInfoAppDescription": "Enlace a la página web de información de la aplicación", - "moreApps": "Mis otras aplicaciones", - "moreAppsDescription": "Más aplicaciones, contacto, donaciones y más", - "selectAnOption": "Selecciona una opción", - "customization": { - "customization": "Personalización", - "customizationDescription": "Configura el tema y la paleta de colores.", - "theme": "Tema", - "light": "Claro", - "dark": "Oscuro", - "systemDefined": "Definido por el sistema", - "color": "Color", - "useDynamicTheme": "Usar tema dinámico" - }, - "generalSettings": { - "generalSettings": "Ajustes generales", - "generalSettingsDescription": "Ajustes generales para la aplicación.", - "bookmarks": "Marcadores", - "showFavicon": "Mostrar favicon", - "showFaviconDescription": "Mostrar el favicon del sitio web en cada marcador.", - "disconnectFromServer": "Desconectar del servidor", - "disconnectModal": { - "title": "Desconectar", - "description": "¿Estás seguro que deseas desconectarte del servidor?\nSerás redirigido a la configuración inicial." - }, - "useInAppBrowser": "Usar navegador de la aplicación", - "useInAppBrowserDescription": "Abre los marcadores con el navegador integrado en vez de con el navegador del sietema. En modo tablet siempre se usará el navegador integrado.", - "openLinksWith": "Abrir enlaces con...", - "internalBrowser": "Navegador interno de la app", - "browserCustomTab": "Pestaña personalizada del navegador", - "systemBrowser": "Navegador del sistema", - "tags": "Etiquetas", - "defaultTags": { - "defaultTags": "Etiquetas por defecto", - "defaultTagsDescription": "Define una lista de etiquetas que se añadirán por defecto al crear un marcador", - "newTag": "Nueva etiqueta", - "addTag": "Añadir etiqueta", - "removeThisTag": "Eliminar esta etiqueta", - "noDefaultTags": "No hay etiquetas por defecto" - }, - "others": "Otros", - "setMarkAsUnreadDefault": "Marcar como no leído por defecto", - "setMarkAsUnreadDefaultDescription": "Habilitar por defecto la opción de marcar como leído al crear un marcador.", - "enableSlideOptions": "Habilitar opciones al deslizar", - "enableSlideOptionsDescription": "Habilitar opciones al deslizar en la lista de marcadores" - } - }, - "webview": { - "goBack": "Ir atrás", - "goForward": "Ir adelante", - "reload": "Recargar", - "openInSystemBrowser": "Abrir en el navegador del sistema", - "copyLinkClipboard": "Copiar enlace al portapapeles", - "linkCopiedClipboard": "Enlace copiado al portapapeles.", - "share": "Compartir", - "invalidBookmarkData": "El marcador tiene datos inválidos o está corrupto." - }, - "colors": { - "red": "Rojo", - "green": "Verde", - "blue": "Azul", - "yellow": "Amarillo", - "orange": "Naranja", - "brown": "Marron", - "cyan": "Cian", - "purple": "Morado", - "pink": "Rosa", - "deepOrange": "Naranja oscuro", - "indigo": "Índigo" - } -} \ No newline at end of file diff --git a/lib/i18n/strings_tr.g.dart b/lib/i18n/strings_tr.g.dart deleted file mode 100644 index 32328bf..0000000 --- a/lib/i18n/strings_tr.g.dart +++ /dev/null @@ -1,659 +0,0 @@ -/// -/// Generated file. Do not edit. -/// -// coverage:ignore-file -// ignore_for_file: type=lint, unused_import -// dart format off - -import 'package:flutter/widgets.dart'; -import 'package:intl/intl.dart'; -import 'package:slang/generated.dart'; -import 'strings.g.dart'; - -// Path: -class TranslationsTr with BaseTranslations implements Translations { - /// You can call this constructor and build your own translation instance of this locale. - /// Constructing via the enum [AppLocale.build] is preferred. - TranslationsTr({Map? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver, TranslationMetadata? meta}) - : assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'), - $meta = meta ?? TranslationMetadata( - locale: AppLocale.tr, - overrides: overrides ?? {}, - cardinalResolver: cardinalResolver, - ordinalResolver: ordinalResolver, - ) { - $meta.setFlatMapFunction(_flatMapFunction); - } - - /// Metadata for the translations of . - @override final TranslationMetadata $meta; - - /// Access flat map - @override dynamic operator[](String key) => $meta.getTranslation(key); - - late final TranslationsTr _root = this; // ignore: unused_field - - @override - TranslationsTr $copyWith({TranslationMetadata? meta}) => TranslationsTr(meta: meta ?? this.$meta); - - // Translations - @override late final _TranslationsGenericTr generic = _TranslationsGenericTr._(_root); - @override late final _TranslationsOnboardingTr onboarding = _TranslationsOnboardingTr._(_root); - @override late final _TranslationsBookmarksTr bookmarks = _TranslationsBookmarksTr._(_root); - @override late final _TranslationsTagsTr tags = _TranslationsTagsTr._(_root); - @override late final _TranslationsSettingsTr settings = _TranslationsSettingsTr._(_root); - @override late final _TranslationsWebviewTr webview = _TranslationsWebviewTr._(_root); - @override late final _TranslationsColorsTr colors = _TranslationsColorsTr._(_root); -} - -// Path: generic -class _TranslationsGenericTr implements TranslationsGenericEn { - _TranslationsGenericTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get confirm => 'Onayla'; - @override String get cancel => 'İptal'; - @override String get next => 'Sonraki'; - @override String get save => 'Kaydet'; - @override String get close => 'Kapat'; - @override String get error => 'Hata'; - @override String get optional => 'İsteğe bağlı'; - @override String get authTokenNotValid => 'Yetkilendirme jetonunuz artık geçerli değil. Lütfen yeniden kimlik doğrulaması yapın.'; - @override String get options => 'Seçenekler'; -} - -// Path: onboarding -class _TranslationsOnboardingTr implements TranslationsOnboardingEn { - _TranslationsOnboardingTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get title => 'Linkdy\'ye hoş geldiniz'; - @override String get subtitle => 'Yer işaretlerinizi yönetmek için bir uygulama.'; - @override String get start => 'Başlat'; - @override String get next => 'Sonraki'; - @override String get previous => 'Önceki'; - @override String get serverRequired => 'Sunucu gerekli'; - @override String get serverRequiredDescription => 'Linkdy bağımsız bir uygulama değildir, Linkding sunucusunun çalışmasını gerektirir.\nBu uygulamayı kullanmak için Linkding\'i ev sunucunuza, VPS\'ye veya başka bir bilgisayara dağıtmanız gerekir.'; - @override String get installationInstructions => 'Resmi GitHub deposundaki kurulum talimatlarını kontrol edin.'; - @override String get serverRunningConfirmation => 'Halihazırda çalışan bir Linkding sunucusu örneğim olduğunu onaylıyorum.'; - @override String get createConnection => 'Bağlantı oluştur'; - @override String get createConnectionSubtitle => 'Sunucunuzla bağlantı kurmak için gerekli tüm ayrıntıları girin.'; - @override String get ipAddressOrDomain => 'IP adresi veya alan adı'; - @override String get port => 'Bağlantı noktası'; - @override String get path => 'Yol'; - @override String get invalidPath => 'Geçersiz yol'; - @override String get token => 'Jeton'; - @override String get required => 'Gerekli'; - @override String get serverDetails => 'Sunucu bilgileri'; - @override String get authentication => 'Kimlik Doğrulama'; - @override String get testConnectionUrl => 'Bağlantı adresini test edin'; - @override String get connectionServerEstablished => 'Sunucu ile bağlantı kuruldu'; - @override String get testingConnection => 'Bağlantı test ediliyor...'; - @override String get connectionServerFailed => 'Sunucu ile bağlantı başarısız oldu'; - @override String get connect => 'Bağlan'; - @override String get connecting => 'Bağlanıyor...'; - @override String get cannotConnectToServer => 'Sunucuya bağlanılamıyor.'; - @override String get invalidToken => 'Geçersiz belirteç.'; - @override String get invalidIpDomain => 'Geçersiz IP adresi veya etki alanı'; - @override String get invalidPort => 'Geçersiz bağlantı noktası'; - @override String get tokenRequired => 'Jeton gereklidir'; -} - -// Path: bookmarks -class _TranslationsBookmarksTr implements TranslationsBookmarksEn { - _TranslationsBookmarksTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get bookmarks => 'Yer İşaretleri'; - @override String get noBookmarksAdded => 'Yer işareti eklenmedi'; - @override String get cannotLoadBookmarks => 'Yer işaretleri yüklenemiyor'; - @override late final _TranslationsBookmarksDatesTr dates = _TranslationsBookmarksDatesTr._(_root); - @override String get shared => 'Ortak'; - @override String get archived => 'Arşivlendi'; - @override String get showOnlyRead => 'Sadece okunanı göster'; - @override String get showOnlyUnread => 'Sadece okunmamışları göster'; - @override String get showAllBookmarks => 'Tüm yer işaretlerini göster'; - @override String get readStatus => 'Okuma durumu'; - @override String get all => 'Tümü'; - @override String get unread => 'Okunmadı'; - @override String get read => 'Oku'; - @override String get filterSort => 'Filtrele ve sırala'; - @override String get sorting => 'Sıralama'; - @override String get date => 'Tarih'; - @override String get title => 'Başlık'; - @override String get ascendant => 'Yükselen'; - @override String get descendant => 'Alt öğe'; - @override late final _TranslationsBookmarksAddBookmarkTr addBookmark = _TranslationsBookmarksAddBookmarkTr._(_root); - @override late final _TranslationsBookmarksSearchTr search = _TranslationsBookmarksSearchTr._(_root); - @override late final _TranslationsBookmarksBookmarkOptionsTr bookmarkOptions = _TranslationsBookmarksBookmarkOptionsTr._(_root); - @override late final _TranslationsBookmarksShareOptionsTr shareOptions = _TranslationsBookmarksShareOptionsTr._(_root); -} - -// Path: tags -class _TranslationsTagsTr implements TranslationsTagsEn { - _TranslationsTagsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get tags => 'Etiketler'; - @override String created({required Object created}) => 'Oluşturuldu: ${created}'; - @override late final _TranslationsTagsCreateTagTr createTag = _TranslationsTagsCreateTagTr._(_root); - @override late final _TranslationsTagsFilteredBookmarksTr filteredBookmarks = _TranslationsTagsFilteredBookmarksTr._(_root); -} - -// Path: settings -class _TranslationsSettingsTr implements TranslationsSettingsEn { - _TranslationsSettingsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get settings => 'Ayarlar'; - @override String get appSettings => 'Uygulama ayarları'; - @override String get aboutApp => 'Uygulama hakkında'; - @override String get appVersion => 'Uygulama sürümü'; - @override String get createdBy => 'Geliştirici'; - @override String get visitGooglePlay => 'Google Play\'deki uygulama sayfasını ziyaret et'; - @override String get visitGitHubRepo => 'GitHub\'daki uygulama deposunu ziyaret et'; - @override String get linkdingRepository => 'Linkding deposu'; - @override String get linkdingRepositoryDescription => 'GitHub\'daki Linkding deposuna bağlantı'; - @override String get moreInfoApp => 'Uygulama hakkında daha fazla bilgi'; - @override String get moreInfoAppDescription => 'Uygulamanın bilgi sayfasına bağlantı'; - @override String get moreApps => 'Diğer uygulamalarım'; - @override String get moreAppsDescription => 'Daha fazla uygulama, iletişim, bağış ve daha fazlası'; - @override String get selectAnOption => 'Bir seçenek seçin'; - @override late final _TranslationsSettingsCustomizationTr customization = _TranslationsSettingsCustomizationTr._(_root); - @override late final _TranslationsSettingsGeneralSettingsTr generalSettings = _TranslationsSettingsGeneralSettingsTr._(_root); -} - -// Path: webview -class _TranslationsWebviewTr implements TranslationsWebviewEn { - _TranslationsWebviewTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get goBack => 'Geri dön'; - @override String get goForward => 'İleri git'; - @override String get reload => 'Yenile'; - @override String get openInSystemBrowser => 'Sistem tarayıcısında aç'; - @override String get copyLinkClipboard => 'Bağlantıyı panoya kopyala'; - @override String get linkCopiedClipboard => 'Bağlantı panoya kopyalandı.'; - @override String get share => 'Paylaş'; - @override String get invalidBookmarkData => 'The bookmark has invalid data or it\'s corrupted.'; -} - -// Path: colors -class _TranslationsColorsTr implements TranslationsColorsEn { - _TranslationsColorsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get red => 'Kırmızı'; - @override String get green => 'Yeşil'; - @override String get blue => 'Mavi'; - @override String get yellow => 'Sarı'; - @override String get orange => 'Turuncu'; - @override String get brown => 'Kahverengi'; - @override String get cyan => 'Camgöbeği'; - @override String get purple => 'Mor'; - @override String get pink => 'Pembe'; - @override String get deepOrange => 'Koyu turuncu'; - @override String get indigo => 'Çivit'; -} - -// Path: bookmarks.dates -class _TranslationsBookmarksDatesTr implements TranslationsBookmarksDatesEn { - _TranslationsBookmarksDatesTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String todayAt({required Object time}) => 'Bugün, ${time}'; - @override String yesterdayAt({required Object time}) => 'Dün, ${time}'; -} - -// Path: bookmarks.addBookmark -class _TranslationsBookmarksAddBookmarkTr implements TranslationsBookmarksAddBookmarkEn { - _TranslationsBookmarksAddBookmarkTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get addBookmark => 'Yeni yer işareti ekle'; - @override String get editBookmark => 'Yer işaretini düzenle'; - @override String get bookmarkUrl => 'Yer İşareti bağlantısı'; - @override String get bookmarkDetails => 'Yer işareti ayrıntıları'; - @override String get validateUrl => 'Bağlantı adresini doğrula'; - @override String get urlValid => 'Bağlantı adresi geçerli'; - @override String get urlNotValid => 'Bağlantı adresi geçerli değil'; - @override String get cannotCheckUrl => 'Bağlantı adresi kontrol edilemedi, ancak yine de kaydedebilirsiniz.'; - @override String get invalidUrl => 'Geçersiz bağlantı adresi'; - @override String get url => 'Bağlantı adresi'; - @override String get checkingUrl => 'Bağlantı adresi kontrol ediliyor...'; - @override String get title => 'Başlık'; - @override String get description => 'Açıklama'; - @override String get markAsUnread => 'Okunmadı olarak işaretle'; - @override String get markAsUnreadDescription => 'Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.'; - @override String get notes => 'Notlar'; - @override String get addNotes => 'Not ekle'; - @override String get tags => 'Etiketler'; - @override String get noTagsAdded => 'Etiket eklenmedi'; - @override String get tagNoWhitespaces => 'Etiket boşluk içeremez'; - @override String get addTag => 'Etiket ekle'; - @override String get others => 'Diğerleri'; - @override String get savingBookmark => 'Yer işareti kaydediliyor...'; - @override String get bookmarkSavedSuccessfully => 'Yer işareti başarıyla kaydedildi.'; - @override String get errorSavingBookmark => 'Yeni yer işareti kaydedilirken bir hata oluştu.'; - @override String get leaveEmptyUseWebsiteTitle => 'Web sitesinin başlığını kullanmak için boş bırakın.'; - @override String get leaveEmptyUseWebsiteDescription => 'Web sitesinin açıklamasını kullanmak için boş bırakın.'; - @override String get share => 'Share'; - @override String get shareDescription => 'Share this bookmark with other registered users and anonymous users.'; - @override String get urlAlreadyBookmarked => 'This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark.'; -} - -// Path: bookmarks.search -class _TranslationsBookmarksSearchTr implements TranslationsBookmarksSearchEn { - _TranslationsBookmarksSearchTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get searchBookmarks => 'Yer işaretlerini ara'; - @override String get clearSearch => 'Aramayı temizle'; - @override String get inputSearchTerm => 'Bir arama terimi girin'; - @override String get cannotSearchError => 'Bir hata nedeniyle içerik aranamıyor'; - @override String get inputtedSearchTermNoResults => 'Girilen arama teriminin herhangi bir sonucu yok'; -} - -// Path: bookmarks.bookmarkOptions -class _TranslationsBookmarksBookmarkOptionsTr implements TranslationsBookmarksBookmarkOptionsEn { - _TranslationsBookmarksBookmarkOptionsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get edit => 'Düzenle'; - @override String get delete => 'Sil'; - @override String get read => 'Oku'; - @override String get unread => 'Okunmadı'; - @override String get markAsUnread => 'Okunmadı olarak işaretle'; - @override String get markAsRead => 'Okundu olarak işaretle'; - @override String get shareOptions => 'Paylaşım seçenekleri'; - @override String get shared => 'Ortak'; - @override String get archive => 'Arşivle'; - @override String get unarchive => 'Arşivden çıkar'; - @override String get deletingBookmark => 'Yer işareti siliniyor...'; - @override String get bookmarkDeleted => 'Yer işareti başarıyla silindi'; - @override String get bookmarkNotDeleted => 'Yer işareti bir hata nedeniyle silinemedi.'; - @override String get deleteBookmark => 'Yer işaretini sil'; - @override String get followingBookmarkDeleted => 'Aşağıdaki yer işareti silinecek:'; - @override String get markingAsRead => 'Okundu olarak işaretleniyor...'; - @override String get markingAsUnead => 'Okunmadı olarak işaretleniyor...'; - @override String get markedAsReadSuccessfully => 'Yer işareti başarıyla okundu olarak işaretlendi.'; - @override String get markedAsUnreadSuccessfully => 'Yer işareti başarıyla okunmadı olarak işaretlendi.'; - @override String get bookmarkNotMarkedAsRead => 'Yer işareti okundu olarak işaretlenemedi.'; - @override String get bookmarkNotMarkedAsUnread => 'Yer işareti okunmadı olarak işaretlenemedi.'; - @override String get archivingBookmark => 'Yer işareti arşivleniyor...'; - @override String get unarchivingBookmark => 'Yer işareti arşivden çıkarılıyor...'; - @override String get bookmarkArchivedSuccessfully => 'Yer işareti başarıyla arşivlendi.'; - @override String get bookmarkUnrchivedSuccessfully => 'Yer işareti başarıyla arşivden kaldırıldı.'; - @override String get bookmarkNotArchived => 'Yer işareti arşivlenemedi.'; - @override String get bookmarkNotUnrchived => 'Yer işareti arşivden çıkarılamadı.'; - @override String get shareThirdPartyApp => 'Üçüncü taraf bir uygulama kullanarak paylaşma'; - @override String get shareInternally => 'Dahili olarak paylaşın'; - @override String get unshareInternally => 'Dahili olarak paylaşımı kaldır'; -} - -// Path: bookmarks.shareOptions -class _TranslationsBookmarksShareOptionsTr implements TranslationsBookmarksShareOptionsEn { - _TranslationsBookmarksShareOptionsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get shareOptions => 'Paylaşım seçenekleri'; - @override String get shareInternally => 'Dahili olarak paylaşın'; - @override String get unshareInternally => 'Dahili olarak paylaşımı kaldır'; - @override String get shareInternallyDescription => 'Bu Linkding örneğinin geri kalan kullanıcılarıyla dahili olarak paylaşın'; - @override String get unshareInternallyDescription => 'Dahili olarak paylaşılan bu yer işaretinin paylaşımını kaldır'; - @override String get shareExternally => 'Yer işareti bağlantısını harici olarak paylaş'; - @override String get shareExternallyDescription => 'Üçüncü taraf bir uygulama kullanarak yer işareti bağlantısını harici olarak paylaşın'; - @override String get sharingBookmark => 'Yer işareti paylaşılıyor...'; - @override String get unsharingBookmark => 'Yer işareti paylaşımı kaldırılıyor...'; - @override String get bookmarkSharedSuccessfully => 'Yer işareti başarıyla paylaşıldı.'; - @override String get bookmarkNotShared => 'Yer işareti paylaşılamadı.'; - @override String get bookmarkUnsharedSuccessfully => 'Yer işareti başarıyla paylaşılmadı.'; - @override String get bookmarkNotUnshared => 'Yer işareti paylaşımı kaldırılamadı.'; -} - -// Path: tags.createTag -class _TranslationsTagsCreateTagTr implements TranslationsTagsCreateTagEn { - _TranslationsTagsCreateTagTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get createTag => 'Etiket oluştur'; - @override String get name => 'Adı'; - @override String get creatingTag => 'Etiket oluşturuluyor...'; - @override String get errorCreatingTag => 'Etiket oluşturulurken bir hata oluştu.'; -} - -// Path: tags.filteredBookmarks -class _TranslationsTagsFilteredBookmarksTr implements TranslationsTagsFilteredBookmarksEn { - _TranslationsTagsFilteredBookmarksTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get noBookmarksWithThisTag => 'Bu etikete sahip yer işareti yok'; - @override String get noArchivedBookmarks => 'Arşivlenmiş yer işareti yok'; - @override String get noSharedBookmarks => 'Paylaşılmış yer işareti yok'; -} - -// Path: settings.customization -class _TranslationsSettingsCustomizationTr implements TranslationsSettingsCustomizationEn { - _TranslationsSettingsCustomizationTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get customization => 'Özelleştirme'; - @override String get customizationDescription => 'Uygulama temasını ve renk paletini ayarlayın.'; - @override String get theme => 'Tema'; - @override String get light => 'Açık'; - @override String get dark => 'Koyu'; - @override String get systemDefined => 'Sistem tanımlı'; - @override String get color => 'Renk'; - @override String get useDynamicTheme => 'Dinamik tema kullan'; -} - -// Path: settings.generalSettings -class _TranslationsSettingsGeneralSettingsTr implements TranslationsSettingsGeneralSettingsEn { - _TranslationsSettingsGeneralSettingsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get generalSettings => 'Genel Ayarlar'; - @override String get generalSettingsDescription => 'Uygulama için genel düzenlemeler.'; - @override String get bookmarks => 'Yer İmleri'; - @override String get showFavicon => 'Site simgesini göster'; - @override String get showFaviconDescription => 'Her yer işaretinde web sitesinin simgesini gösterin.'; - @override String get disconnectFromServer => 'Sunucu ile bağlantıyı kes'; - @override late final _TranslationsSettingsGeneralSettingsDisconnectModalTr disconnectModal = _TranslationsSettingsGeneralSettingsDisconnectModalTr._(_root); - @override String get useInAppBrowser => 'Uygulama tarayıcısında kullanın'; - @override String get useInAppBrowserDescription => 'Yer işaretlerini sistem tarayıcısı yerine entegre tarayıcı ile açar. Tablet modunda dahili tarayıcı her zaman kullanılacaktır.'; - @override String get openLinksWith => 'Open links with...'; - @override String get internalBrowser => 'App internal browser'; - @override String get browserCustomTab => 'Browser custom tab'; - @override String get systemBrowser => 'System browser'; - @override String get tags => 'Tags'; - @override late final _TranslationsSettingsGeneralSettingsDefaultTagsTr defaultTags = _TranslationsSettingsGeneralSettingsDefaultTagsTr._(_root); - @override String get others => 'Others'; - @override String get setMarkAsUnreadDefault => 'Set mark as unread by default'; - @override String get setMarkAsUnreadDefaultDescription => 'Set the mark as unread option by default when creating a new bookmark.'; - @override String get enableSlideOptions => 'Enable slide options'; - @override String get enableSlideOptionsDescription => 'Enable slide options on the bookmark list'; -} - -// Path: settings.generalSettings.disconnectModal -class _TranslationsSettingsGeneralSettingsDisconnectModalTr implements TranslationsSettingsGeneralSettingsDisconnectModalEn { - _TranslationsSettingsGeneralSettingsDisconnectModalTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get title => 'Bağlantıyı kes'; - @override String get description => 'Sunucu bağlantısını kesmek istediğinizden emin misiniz?\nİlk kuruluma yönlendirileceksiniz.'; -} - -// Path: settings.generalSettings.defaultTags -class _TranslationsSettingsGeneralSettingsDefaultTagsTr implements TranslationsSettingsGeneralSettingsDefaultTagsEn { - _TranslationsSettingsGeneralSettingsDefaultTagsTr._(this._root); - - final TranslationsTr _root; // ignore: unused_field - - // Translations - @override String get defaultTags => 'Default tags'; - @override String get defaultTagsDescription => 'Define a list of tags that will be added by default when creating a bookmark'; - @override String get newTag => 'New tag'; - @override String get addTag => 'AddTag'; - @override String get removeThisTag => 'Remove this tag'; - @override String get noDefaultTags => 'There are no default tags'; -} - -/// The flat map containing all translations for locale . -/// Only for edge cases! For simple maps, use the map function of this library. -/// -/// The Dart AOT compiler has issues with very large switch statements, -/// so the map is split into smaller functions (512 entries each). -extension on TranslationsTr { - dynamic _flatMapFunction(String path) { - return switch (path) { - 'generic.confirm' => 'Onayla', - 'generic.cancel' => 'İptal', - 'generic.next' => 'Sonraki', - 'generic.save' => 'Kaydet', - 'generic.close' => 'Kapat', - 'generic.error' => 'Hata', - 'generic.optional' => 'İsteğe bağlı', - 'generic.authTokenNotValid' => 'Yetkilendirme jetonunuz artık geçerli değil. Lütfen yeniden kimlik doğrulaması yapın.', - 'generic.options' => 'Seçenekler', - 'onboarding.title' => 'Linkdy\'ye hoş geldiniz', - 'onboarding.subtitle' => 'Yer işaretlerinizi yönetmek için bir uygulama.', - 'onboarding.start' => 'Başlat', - 'onboarding.next' => 'Sonraki', - 'onboarding.previous' => 'Önceki', - 'onboarding.serverRequired' => 'Sunucu gerekli', - 'onboarding.serverRequiredDescription' => 'Linkdy bağımsız bir uygulama değildir, Linkding sunucusunun çalışmasını gerektirir.\nBu uygulamayı kullanmak için Linkding\'i ev sunucunuza, VPS\'ye veya başka bir bilgisayara dağıtmanız gerekir.', - 'onboarding.installationInstructions' => 'Resmi GitHub deposundaki kurulum talimatlarını kontrol edin.', - 'onboarding.serverRunningConfirmation' => 'Halihazırda çalışan bir Linkding sunucusu örneğim olduğunu onaylıyorum.', - 'onboarding.createConnection' => 'Bağlantı oluştur', - 'onboarding.createConnectionSubtitle' => 'Sunucunuzla bağlantı kurmak için gerekli tüm ayrıntıları girin.', - 'onboarding.ipAddressOrDomain' => 'IP adresi veya alan adı', - 'onboarding.port' => 'Bağlantı noktası', - 'onboarding.path' => 'Yol', - 'onboarding.invalidPath' => 'Geçersiz yol', - 'onboarding.token' => 'Jeton', - 'onboarding.required' => 'Gerekli', - 'onboarding.serverDetails' => 'Sunucu bilgileri', - 'onboarding.authentication' => 'Kimlik Doğrulama', - 'onboarding.testConnectionUrl' => 'Bağlantı adresini test edin', - 'onboarding.connectionServerEstablished' => 'Sunucu ile bağlantı kuruldu', - 'onboarding.testingConnection' => 'Bağlantı test ediliyor...', - 'onboarding.connectionServerFailed' => 'Sunucu ile bağlantı başarısız oldu', - 'onboarding.connect' => 'Bağlan', - 'onboarding.connecting' => 'Bağlanıyor...', - 'onboarding.cannotConnectToServer' => 'Sunucuya bağlanılamıyor.', - 'onboarding.invalidToken' => 'Geçersiz belirteç.', - 'onboarding.invalidIpDomain' => 'Geçersiz IP adresi veya etki alanı', - 'onboarding.invalidPort' => 'Geçersiz bağlantı noktası', - 'onboarding.tokenRequired' => 'Jeton gereklidir', - 'bookmarks.bookmarks' => 'Yer İşaretleri', - 'bookmarks.noBookmarksAdded' => 'Yer işareti eklenmedi', - 'bookmarks.cannotLoadBookmarks' => 'Yer işaretleri yüklenemiyor', - 'bookmarks.dates.todayAt' => ({required Object time}) => 'Bugün, ${time}', - 'bookmarks.dates.yesterdayAt' => ({required Object time}) => 'Dün, ${time}', - 'bookmarks.shared' => 'Ortak', - 'bookmarks.archived' => 'Arşivlendi', - 'bookmarks.showOnlyRead' => 'Sadece okunanı göster', - 'bookmarks.showOnlyUnread' => 'Sadece okunmamışları göster', - 'bookmarks.showAllBookmarks' => 'Tüm yer işaretlerini göster', - 'bookmarks.readStatus' => 'Okuma durumu', - 'bookmarks.all' => 'Tümü', - 'bookmarks.unread' => 'Okunmadı', - 'bookmarks.read' => 'Oku', - 'bookmarks.filterSort' => 'Filtrele ve sırala', - 'bookmarks.sorting' => 'Sıralama', - 'bookmarks.date' => 'Tarih', - 'bookmarks.title' => 'Başlık', - 'bookmarks.ascendant' => 'Yükselen', - 'bookmarks.descendant' => 'Alt öğe', - 'bookmarks.addBookmark.addBookmark' => 'Yeni yer işareti ekle', - 'bookmarks.addBookmark.editBookmark' => 'Yer işaretini düzenle', - 'bookmarks.addBookmark.bookmarkUrl' => 'Yer İşareti bağlantısı', - 'bookmarks.addBookmark.bookmarkDetails' => 'Yer işareti ayrıntıları', - 'bookmarks.addBookmark.validateUrl' => 'Bağlantı adresini doğrula', - 'bookmarks.addBookmark.urlValid' => 'Bağlantı adresi geçerli', - 'bookmarks.addBookmark.urlNotValid' => 'Bağlantı adresi geçerli değil', - 'bookmarks.addBookmark.cannotCheckUrl' => 'Bağlantı adresi kontrol edilemedi, ancak yine de kaydedebilirsiniz.', - 'bookmarks.addBookmark.invalidUrl' => 'Geçersiz bağlantı adresi', - 'bookmarks.addBookmark.url' => 'Bağlantı adresi', - 'bookmarks.addBookmark.checkingUrl' => 'Bağlantı adresi kontrol ediliyor...', - 'bookmarks.addBookmark.title' => 'Başlık', - 'bookmarks.addBookmark.description' => 'Açıklama', - 'bookmarks.addBookmark.markAsUnread' => 'Okunmadı olarak işaretle', - 'bookmarks.addBookmark.markAsUnreadDescription' => 'Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.', - 'bookmarks.addBookmark.notes' => 'Notlar', - 'bookmarks.addBookmark.addNotes' => 'Not ekle', - 'bookmarks.addBookmark.tags' => 'Etiketler', - 'bookmarks.addBookmark.noTagsAdded' => 'Etiket eklenmedi', - 'bookmarks.addBookmark.tagNoWhitespaces' => 'Etiket boşluk içeremez', - 'bookmarks.addBookmark.addTag' => 'Etiket ekle', - 'bookmarks.addBookmark.others' => 'Diğerleri', - 'bookmarks.addBookmark.savingBookmark' => 'Yer işareti kaydediliyor...', - 'bookmarks.addBookmark.bookmarkSavedSuccessfully' => 'Yer işareti başarıyla kaydedildi.', - 'bookmarks.addBookmark.errorSavingBookmark' => 'Yeni yer işareti kaydedilirken bir hata oluştu.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteTitle' => 'Web sitesinin başlığını kullanmak için boş bırakın.', - 'bookmarks.addBookmark.leaveEmptyUseWebsiteDescription' => 'Web sitesinin açıklamasını kullanmak için boş bırakın.', - 'bookmarks.addBookmark.share' => 'Share', - 'bookmarks.addBookmark.shareDescription' => 'Share this bookmark with other registered users and anonymous users.', - 'bookmarks.addBookmark.urlAlreadyBookmarked' => 'This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark.', - 'bookmarks.search.searchBookmarks' => 'Yer işaretlerini ara', - 'bookmarks.search.clearSearch' => 'Aramayı temizle', - 'bookmarks.search.inputSearchTerm' => 'Bir arama terimi girin', - 'bookmarks.search.cannotSearchError' => 'Bir hata nedeniyle içerik aranamıyor', - 'bookmarks.search.inputtedSearchTermNoResults' => 'Girilen arama teriminin herhangi bir sonucu yok', - 'bookmarks.bookmarkOptions.edit' => 'Düzenle', - 'bookmarks.bookmarkOptions.delete' => 'Sil', - 'bookmarks.bookmarkOptions.read' => 'Oku', - 'bookmarks.bookmarkOptions.unread' => 'Okunmadı', - 'bookmarks.bookmarkOptions.markAsUnread' => 'Okunmadı olarak işaretle', - 'bookmarks.bookmarkOptions.markAsRead' => 'Okundu olarak işaretle', - 'bookmarks.bookmarkOptions.shareOptions' => 'Paylaşım seçenekleri', - 'bookmarks.bookmarkOptions.shared' => 'Ortak', - 'bookmarks.bookmarkOptions.archive' => 'Arşivle', - 'bookmarks.bookmarkOptions.unarchive' => 'Arşivden çıkar', - 'bookmarks.bookmarkOptions.deletingBookmark' => 'Yer işareti siliniyor...', - 'bookmarks.bookmarkOptions.bookmarkDeleted' => 'Yer işareti başarıyla silindi', - 'bookmarks.bookmarkOptions.bookmarkNotDeleted' => 'Yer işareti bir hata nedeniyle silinemedi.', - 'bookmarks.bookmarkOptions.deleteBookmark' => 'Yer işaretini sil', - 'bookmarks.bookmarkOptions.followingBookmarkDeleted' => 'Aşağıdaki yer işareti silinecek:', - 'bookmarks.bookmarkOptions.markingAsRead' => 'Okundu olarak işaretleniyor...', - 'bookmarks.bookmarkOptions.markingAsUnead' => 'Okunmadı olarak işaretleniyor...', - 'bookmarks.bookmarkOptions.markedAsReadSuccessfully' => 'Yer işareti başarıyla okundu olarak işaretlendi.', - 'bookmarks.bookmarkOptions.markedAsUnreadSuccessfully' => 'Yer işareti başarıyla okunmadı olarak işaretlendi.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead' => 'Yer işareti okundu olarak işaretlenemedi.', - 'bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread' => 'Yer işareti okunmadı olarak işaretlenemedi.', - 'bookmarks.bookmarkOptions.archivingBookmark' => 'Yer işareti arşivleniyor...', - 'bookmarks.bookmarkOptions.unarchivingBookmark' => 'Yer işareti arşivden çıkarılıyor...', - 'bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully' => 'Yer işareti başarıyla arşivlendi.', - 'bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully' => 'Yer işareti başarıyla arşivden kaldırıldı.', - 'bookmarks.bookmarkOptions.bookmarkNotArchived' => 'Yer işareti arşivlenemedi.', - 'bookmarks.bookmarkOptions.bookmarkNotUnrchived' => 'Yer işareti arşivden çıkarılamadı.', - 'bookmarks.bookmarkOptions.shareThirdPartyApp' => 'Üçüncü taraf bir uygulama kullanarak paylaşma', - 'bookmarks.bookmarkOptions.shareInternally' => 'Dahili olarak paylaşın', - 'bookmarks.bookmarkOptions.unshareInternally' => 'Dahili olarak paylaşımı kaldır', - 'bookmarks.shareOptions.shareOptions' => 'Paylaşım seçenekleri', - 'bookmarks.shareOptions.shareInternally' => 'Dahili olarak paylaşın', - 'bookmarks.shareOptions.unshareInternally' => 'Dahili olarak paylaşımı kaldır', - 'bookmarks.shareOptions.shareInternallyDescription' => 'Bu Linkding örneğinin geri kalan kullanıcılarıyla dahili olarak paylaşın', - 'bookmarks.shareOptions.unshareInternallyDescription' => 'Dahili olarak paylaşılan bu yer işaretinin paylaşımını kaldır', - 'bookmarks.shareOptions.shareExternally' => 'Yer işareti bağlantısını harici olarak paylaş', - 'bookmarks.shareOptions.shareExternallyDescription' => 'Üçüncü taraf bir uygulama kullanarak yer işareti bağlantısını harici olarak paylaşın', - 'bookmarks.shareOptions.sharingBookmark' => 'Yer işareti paylaşılıyor...', - 'bookmarks.shareOptions.unsharingBookmark' => 'Yer işareti paylaşımı kaldırılıyor...', - 'bookmarks.shareOptions.bookmarkSharedSuccessfully' => 'Yer işareti başarıyla paylaşıldı.', - 'bookmarks.shareOptions.bookmarkNotShared' => 'Yer işareti paylaşılamadı.', - 'bookmarks.shareOptions.bookmarkUnsharedSuccessfully' => 'Yer işareti başarıyla paylaşılmadı.', - 'bookmarks.shareOptions.bookmarkNotUnshared' => 'Yer işareti paylaşımı kaldırılamadı.', - 'tags.tags' => 'Etiketler', - 'tags.created' => ({required Object created}) => 'Oluşturuldu: ${created}', - 'tags.createTag.createTag' => 'Etiket oluştur', - 'tags.createTag.name' => 'Adı', - 'tags.createTag.creatingTag' => 'Etiket oluşturuluyor...', - 'tags.createTag.errorCreatingTag' => 'Etiket oluşturulurken bir hata oluştu.', - 'tags.filteredBookmarks.noBookmarksWithThisTag' => 'Bu etikete sahip yer işareti yok', - 'tags.filteredBookmarks.noArchivedBookmarks' => 'Arşivlenmiş yer işareti yok', - 'tags.filteredBookmarks.noSharedBookmarks' => 'Paylaşılmış yer işareti yok', - 'settings.settings' => 'Ayarlar', - 'settings.appSettings' => 'Uygulama ayarları', - 'settings.aboutApp' => 'Uygulama hakkında', - 'settings.appVersion' => 'Uygulama sürümü', - 'settings.createdBy' => 'Geliştirici', - 'settings.visitGooglePlay' => 'Google Play\'deki uygulama sayfasını ziyaret et', - 'settings.visitGitHubRepo' => 'GitHub\'daki uygulama deposunu ziyaret et', - 'settings.linkdingRepository' => 'Linkding deposu', - 'settings.linkdingRepositoryDescription' => 'GitHub\'daki Linkding deposuna bağlantı', - 'settings.moreInfoApp' => 'Uygulama hakkında daha fazla bilgi', - 'settings.moreInfoAppDescription' => 'Uygulamanın bilgi sayfasına bağlantı', - 'settings.moreApps' => 'Diğer uygulamalarım', - 'settings.moreAppsDescription' => 'Daha fazla uygulama, iletişim, bağış ve daha fazlası', - 'settings.selectAnOption' => 'Bir seçenek seçin', - 'settings.customization.customization' => 'Özelleştirme', - 'settings.customization.customizationDescription' => 'Uygulama temasını ve renk paletini ayarlayın.', - 'settings.customization.theme' => 'Tema', - 'settings.customization.light' => 'Açık', - 'settings.customization.dark' => 'Koyu', - 'settings.customization.systemDefined' => 'Sistem tanımlı', - 'settings.customization.color' => 'Renk', - 'settings.customization.useDynamicTheme' => 'Dinamik tema kullan', - 'settings.generalSettings.generalSettings' => 'Genel Ayarlar', - 'settings.generalSettings.generalSettingsDescription' => 'Uygulama için genel düzenlemeler.', - 'settings.generalSettings.bookmarks' => 'Yer İmleri', - 'settings.generalSettings.showFavicon' => 'Site simgesini göster', - 'settings.generalSettings.showFaviconDescription' => 'Her yer işaretinde web sitesinin simgesini gösterin.', - 'settings.generalSettings.disconnectFromServer' => 'Sunucu ile bağlantıyı kes', - 'settings.generalSettings.disconnectModal.title' => 'Bağlantıyı kes', - 'settings.generalSettings.disconnectModal.description' => 'Sunucu bağlantısını kesmek istediğinizden emin misiniz?\nİlk kuruluma yönlendirileceksiniz.', - 'settings.generalSettings.useInAppBrowser' => 'Uygulama tarayıcısında kullanın', - 'settings.generalSettings.useInAppBrowserDescription' => 'Yer işaretlerini sistem tarayıcısı yerine entegre tarayıcı ile açar. Tablet modunda dahili tarayıcı her zaman kullanılacaktır.', - 'settings.generalSettings.openLinksWith' => 'Open links with...', - 'settings.generalSettings.internalBrowser' => 'App internal browser', - 'settings.generalSettings.browserCustomTab' => 'Browser custom tab', - 'settings.generalSettings.systemBrowser' => 'System browser', - 'settings.generalSettings.tags' => 'Tags', - 'settings.generalSettings.defaultTags.defaultTags' => 'Default tags', - 'settings.generalSettings.defaultTags.defaultTagsDescription' => 'Define a list of tags that will be added by default when creating a bookmark', - 'settings.generalSettings.defaultTags.newTag' => 'New tag', - 'settings.generalSettings.defaultTags.addTag' => 'AddTag', - 'settings.generalSettings.defaultTags.removeThisTag' => 'Remove this tag', - 'settings.generalSettings.defaultTags.noDefaultTags' => 'There are no default tags', - 'settings.generalSettings.others' => 'Others', - 'settings.generalSettings.setMarkAsUnreadDefault' => 'Set mark as unread by default', - 'settings.generalSettings.setMarkAsUnreadDefaultDescription' => 'Set the mark as unread option by default when creating a new bookmark.', - 'settings.generalSettings.enableSlideOptions' => 'Enable slide options', - 'settings.generalSettings.enableSlideOptionsDescription' => 'Enable slide options on the bookmark list', - 'webview.goBack' => 'Geri dön', - 'webview.goForward' => 'İleri git', - 'webview.reload' => 'Yenile', - 'webview.openInSystemBrowser' => 'Sistem tarayıcısında aç', - 'webview.copyLinkClipboard' => 'Bağlantıyı panoya kopyala', - 'webview.linkCopiedClipboard' => 'Bağlantı panoya kopyalandı.', - 'webview.share' => 'Paylaş', - 'webview.invalidBookmarkData' => 'The bookmark has invalid data or it\'s corrupted.', - 'colors.red' => 'Kırmızı', - 'colors.green' => 'Yeşil', - 'colors.blue' => 'Mavi', - 'colors.yellow' => 'Sarı', - 'colors.orange' => 'Turuncu', - 'colors.brown' => 'Kahverengi', - 'colors.cyan' => 'Camgöbeği', - 'colors.purple' => 'Mor', - 'colors.pink' => 'Pembe', - 'colors.deepOrange' => 'Koyu turuncu', - 'colors.indigo' => 'Çivit', - _ => null, - }; - } -} diff --git a/lib/i18n/strings_tr.i18n.json b/lib/i18n/strings_tr.i18n.json deleted file mode 100644 index a071fcd..0000000 --- a/lib/i18n/strings_tr.i18n.json +++ /dev/null @@ -1,251 +0,0 @@ -{ - "generic": { - "confirm": "Onayla", - "cancel": "İptal", - "next": "Sonraki", - "save": "Kaydet", - "close": "Kapat", - "error": "Hata", - "optional": "İsteğe bağlı", - "authTokenNotValid": "Yetkilendirme jetonunuz artık geçerli değil. Lütfen yeniden kimlik doğrulaması yapın.", - "options": "Seçenekler" - }, - "onboarding": { - "title": "Linkdy'ye hoş geldiniz", - "subtitle": "Yer işaretlerinizi yönetmek için bir uygulama.", - "start": "Başlat", - "next": "Sonraki", - "previous": "Önceki", - "serverRequired": "Sunucu gerekli", - "serverRequiredDescription": "Linkdy bağımsız bir uygulama değildir, Linkding sunucusunun çalışmasını gerektirir.\nBu uygulamayı kullanmak için Linkding'i ev sunucunuza, VPS'ye veya başka bir bilgisayara dağıtmanız gerekir.", - "installationInstructions": "Resmi GitHub deposundaki kurulum talimatlarını kontrol edin.", - "serverRunningConfirmation": "Halihazırda çalışan bir Linkding sunucusu örneğim olduğunu onaylıyorum.", - "createConnection": "Bağlantı oluştur", - "createConnectionSubtitle": "Sunucunuzla bağlantı kurmak için gerekli tüm ayrıntıları girin.", - "ipAddressOrDomain": "IP adresi veya alan adı", - "port": "Bağlantı noktası", - "path": "Yol", - "invalidPath": "Geçersiz yol", - "token": "Jeton", - "required": "Gerekli", - "serverDetails": "Sunucu bilgileri", - "authentication": "Kimlik Doğrulama", - "testConnectionUrl": "Bağlantı adresini test edin", - "connectionServerEstablished": "Sunucu ile bağlantı kuruldu", - "testingConnection": "Bağlantı test ediliyor...", - "connectionServerFailed": "Sunucu ile bağlantı başarısız oldu", - "connect": "Bağlan", - "connecting": "Bağlanıyor...", - "cannotConnectToServer": "Sunucuya bağlanılamıyor.", - "invalidToken": "Geçersiz belirteç.", - "invalidIpDomain": "Geçersiz IP adresi veya etki alanı", - "invalidPort": "Geçersiz bağlantı noktası", - "tokenRequired": "Jeton gereklidir" - }, - "bookmarks": { - "bookmarks": "Yer İşaretleri", - "noBookmarksAdded": "Yer işareti eklenmedi", - "cannotLoadBookmarks": "Yer işaretleri yüklenemiyor", - "dates": { - "todayAt": "Bugün, $time", - "yesterdayAt": "Dün, $time" - }, - "shared": "Ortak", - "archived": "Arşivlendi", - "showOnlyRead": "Sadece okunanı göster", - "showOnlyUnread": "Sadece okunmamışları göster", - "showAllBookmarks": "Tüm yer işaretlerini göster", - "readStatus": "Okuma durumu", - "all": "Tümü", - "unread": "Okunmadı", - "read": "Oku", - "filterSort": "Filtrele ve sırala", - "sorting": "Sıralama", - "date": "Tarih", - "title": "Başlık", - "ascendant": "Yükselen", - "descendant": "Alt öğe", - "addBookmark": { - "addBookmark": "Yeni yer işareti ekle", - "editBookmark": "Yer işaretini düzenle", - "bookmarkUrl": "Yer İşareti bağlantısı", - "bookmarkDetails": "Yer işareti ayrıntıları", - "validateUrl": "Bağlantı adresini doğrula", - "urlValid": "Bağlantı adresi geçerli", - "urlNotValid": "Bağlantı adresi geçerli değil", - "cannotCheckUrl": "Bağlantı adresi kontrol edilemedi, ancak yine de kaydedebilirsiniz.", - "invalidUrl": "Geçersiz bağlantı adresi", - "url": "Bağlantı adresi", - "checkingUrl": "Bağlantı adresi kontrol ediliyor...", - "title": "Başlık", - "description": "Açıklama", - "markAsUnread": "Okunmadı olarak işaretle", - "markAsUnreadDescription": "Unread bookmarks can be filtered for, and marked as read after you had a chance to look at them.", - "notes": "Notlar", - "addNotes": "Not ekle", - "tags": "Etiketler", - "noTagsAdded": "Etiket eklenmedi", - "tagNoWhitespaces": "Etiket boşluk içeremez", - "addTag": "Etiket ekle", - "others": "Diğerleri", - "savingBookmark": "Yer işareti kaydediliyor...", - "bookmarkSavedSuccessfully": "Yer işareti başarıyla kaydedildi.", - "errorSavingBookmark": "Yeni yer işareti kaydedilirken bir hata oluştu.", - "leaveEmptyUseWebsiteTitle": "Web sitesinin başlığını kullanmak için boş bırakın.", - "leaveEmptyUseWebsiteDescription": "Web sitesinin açıklamasını kullanmak için boş bırakın.", - "share": "Share", - "shareDescription": "Share this bookmark with other registered users and anonymous users.", - "urlAlreadyBookmarked": "This URL is already bookmarked. The form has been pre-filled with the existing bookmark, and saving the form will update the existing bookmark." - }, - "search": { - "searchBookmarks": "Yer işaretlerini ara", - "clearSearch": "Aramayı temizle", - "inputSearchTerm": "Bir arama terimi girin", - "cannotSearchError": "Bir hata nedeniyle içerik aranamıyor", - "inputtedSearchTermNoResults": "Girilen arama teriminin herhangi bir sonucu yok" - }, - "bookmarkOptions": { - "edit": "Düzenle", - "delete": "Sil", - "read": "Oku", - "unread": "Okunmadı", - "markAsUnread": "Okunmadı olarak işaretle", - "markAsRead": "Okundu olarak işaretle", - "shareOptions": "Paylaşım seçenekleri", - "shared": "Ortak", - "archive": "Arşivle", - "unarchive": "Arşivden çıkar", - "deletingBookmark": "Yer işareti siliniyor...", - "bookmarkDeleted": "Yer işareti başarıyla silindi", - "bookmarkNotDeleted": "Yer işareti bir hata nedeniyle silinemedi.", - "deleteBookmark": "Yer işaretini sil", - "followingBookmarkDeleted": "Aşağıdaki yer işareti silinecek:", - "markingAsRead": "Okundu olarak işaretleniyor...", - "markingAsUnead": "Okunmadı olarak işaretleniyor...", - "markedAsReadSuccessfully": "Yer işareti başarıyla okundu olarak işaretlendi.", - "markedAsUnreadSuccessfully": "Yer işareti başarıyla okunmadı olarak işaretlendi.", - "bookmarkNotMarkedAsRead": "Yer işareti okundu olarak işaretlenemedi.", - "bookmarkNotMarkedAsUnread": "Yer işareti okunmadı olarak işaretlenemedi.", - "archivingBookmark": "Yer işareti arşivleniyor...", - "unarchivingBookmark": "Yer işareti arşivden çıkarılıyor...", - "bookmarkArchivedSuccessfully": "Yer işareti başarıyla arşivlendi.", - "bookmarkUnrchivedSuccessfully": "Yer işareti başarıyla arşivden kaldırıldı.", - "bookmarkNotArchived": "Yer işareti arşivlenemedi.", - "bookmarkNotUnrchived": "Yer işareti arşivden çıkarılamadı.", - "shareThirdPartyApp": "Üçüncü taraf bir uygulama kullanarak paylaşma", - "shareInternally": "Dahili olarak paylaşın", - "unshareInternally": "Dahili olarak paylaşımı kaldır" - }, - "shareOptions": { - "shareOptions": "Paylaşım seçenekleri", - "shareInternally": "Dahili olarak paylaşın", - "unshareInternally": "Dahili olarak paylaşımı kaldır", - "shareInternallyDescription": "Bu Linkding örneğinin geri kalan kullanıcılarıyla dahili olarak paylaşın", - "unshareInternallyDescription": "Dahili olarak paylaşılan bu yer işaretinin paylaşımını kaldır", - "shareExternally": "Yer işareti bağlantısını harici olarak paylaş", - "shareExternallyDescription": "Üçüncü taraf bir uygulama kullanarak yer işareti bağlantısını harici olarak paylaşın", - "sharingBookmark": "Yer işareti paylaşılıyor...", - "unsharingBookmark": "Yer işareti paylaşımı kaldırılıyor...", - "bookmarkSharedSuccessfully": "Yer işareti başarıyla paylaşıldı.", - "bookmarkNotShared": "Yer işareti paylaşılamadı.", - "bookmarkUnsharedSuccessfully": "Yer işareti başarıyla paylaşılmadı.", - "bookmarkNotUnshared": "Yer işareti paylaşımı kaldırılamadı." - } - }, - "tags": { - "tags": "Etiketler", - "created": "Oluşturuldu: $created", - "createTag": { - "createTag": "Etiket oluştur", - "name": "Adı", - "creatingTag": "Etiket oluşturuluyor...", - "errorCreatingTag": "Etiket oluşturulurken bir hata oluştu." - }, - "filteredBookmarks": { - "noBookmarksWithThisTag": "Bu etikete sahip yer işareti yok", - "noArchivedBookmarks": "Arşivlenmiş yer işareti yok", - "noSharedBookmarks": "Paylaşılmış yer işareti yok" - } - }, - "settings": { - "settings": "Ayarlar", - "appSettings": "Uygulama ayarları", - "aboutApp": "Uygulama hakkında", - "appVersion": "Uygulama sürümü", - "createdBy": "Geliştirici", - "visitGooglePlay": "Google Play'deki uygulama sayfasını ziyaret et", - "visitGitHubRepo": "GitHub'daki uygulama deposunu ziyaret et", - "linkdingRepository": "Linkding deposu", - "linkdingRepositoryDescription": "GitHub'daki Linkding deposuna bağlantı", - "moreInfoApp": "Uygulama hakkında daha fazla bilgi", - "moreInfoAppDescription": "Uygulamanın bilgi sayfasına bağlantı", - "moreApps": "Diğer uygulamalarım", - "moreAppsDescription": "Daha fazla uygulama, iletişim, bağış ve daha fazlası", - "selectAnOption": "Bir seçenek seçin", - "customization": { - "customization": "Özelleştirme", - "customizationDescription": "Uygulama temasını ve renk paletini ayarlayın.", - "theme": "Tema", - "light": "Açık", - "dark": "Koyu", - "systemDefined": "Sistem tanımlı", - "color": "Renk", - "useDynamicTheme": "Dinamik tema kullan" - }, - "generalSettings": { - "generalSettings": "Genel Ayarlar", - "generalSettingsDescription": "Uygulama için genel düzenlemeler.", - "bookmarks": "Yer İmleri", - "showFavicon": "Site simgesini göster", - "showFaviconDescription": "Her yer işaretinde web sitesinin simgesini gösterin.", - "disconnectFromServer": "Sunucu ile bağlantıyı kes", - "disconnectModal": { - "title": "Bağlantıyı kes", - "description": "Sunucu bağlantısını kesmek istediğinizden emin misiniz?\nİlk kuruluma yönlendirileceksiniz." - }, - "useInAppBrowser": "Uygulama tarayıcısında kullanın", - "useInAppBrowserDescription": "Yer işaretlerini sistem tarayıcısı yerine entegre tarayıcı ile açar. Tablet modunda dahili tarayıcı her zaman kullanılacaktır.", - "openLinksWith": "Open links with...", - "internalBrowser": "App internal browser", - "browserCustomTab": "Browser custom tab", - "systemBrowser": "System browser", - "tags": "Tags", - "defaultTags": { - "defaultTags": "Default tags", - "defaultTagsDescription": "Define a list of tags that will be added by default when creating a bookmark", - "newTag": "New tag", - "addTag": "AddTag", - "removeThisTag": "Remove this tag", - "noDefaultTags": "There are no default tags" - }, - "others": "Others", - "setMarkAsUnreadDefault": "Set mark as unread by default", - "setMarkAsUnreadDefaultDescription": "Set the mark as unread option by default when creating a new bookmark.", - "enableSlideOptions": "Enable slide options", - "enableSlideOptionsDescription": "Enable slide options on the bookmark list" - } - }, - "webview": { - "goBack": "Geri dön", - "goForward": "İleri git", - "reload": "Yenile", - "openInSystemBrowser": "Sistem tarayıcısında aç", - "copyLinkClipboard": "Bağlantıyı panoya kopyala", - "linkCopiedClipboard": "Bağlantı panoya kopyalandı.", - "share": "Paylaş", - "invalidBookmarkData": "The bookmark has invalid data or it's corrupted." - }, - "colors": { - "red": "Kırmızı", - "green": "Yeşil", - "blue": "Mavi", - "yellow": "Sarı", - "orange": "Turuncu", - "brown": "Kahverengi", - "cyan": "Camgöbeği", - "purple": "Mor", - "pink": "Pembe", - "deepOrange": "Koyu turuncu", - "indigo": "Çivit" - } -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart deleted file mode 100644 index 437e621..0000000 --- a/lib/main.dart +++ /dev/null @@ -1,136 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:dynamic_color/dynamic_color.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:linkdy/utils/sentry_handle_error.dart'; -import 'package:package_info_plus/package_info_plus.dart'; -import 'package:listen_sharing_intent/listen_sharing_intent.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/providers/app_info.provider.dart'; -import 'package:linkdy/providers/receive_sharing_intent_url.provider.dart'; -import 'package:linkdy/config/theme.dart'; -import 'package:linkdy/constants/colors.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/providers/shared_preferences.provider.dart'; -import 'package:linkdy/utils/http_overrides.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - - LocaleSettings.useDeviceLocale(); - - HttpOverrides.global = MyHttpOverrides(); - - await dotenv.load(fileName: '.env'); - - final sharedPreferences = await SharedPreferences.getInstance(); - - final appInfo = await PackageInfo.fromPlatform(); - - void startApp() => runApp( - TranslationProvider( - child: ProviderScope( - overrides: [ - sharedPreferencesProvider.overrideWithValue(sharedPreferences), - appInfoProvider.overrideWithValue(appInfo), - ], - child: const MyApp(), - ), - ), - ); - - if ((kReleaseMode && (dotenv.env['SENTRY_DSN'] != null && dotenv.env['SENTRY_DSN'] != "")) || - (dotenv.env['ENABLE_SENTRY'] == "true" && (dotenv.env['SENTRY_DSN'] != null && dotenv.env['SENTRY_DSN'] != ""))) { - SentryFlutter.init( - (options) { - options.dsn = dotenv.env['SENTRY_DSN']; - options.sendDefaultPii = false; - options.beforeSend = sentryHandleError; - }, - appRunner: () => startApp(), - ); - } else { - startApp(); - } -} - -class MyApp extends StatefulHookConsumerWidget { - const MyApp({super.key}); - - @override - ConsumerState createState() => _MyAppState(); -} - -class _MyAppState extends ConsumerState { - @override - void initState() { - super.initState(); - - ReceiveSharingIntent.instance.getMediaStream().listen( - (value) { - if (value.isNotEmpty && - (value.first.type == SharedMediaType.url || (value.first.type == SharedMediaType.text))) { - ref.read(receiveSharingIntentUrlProvider.notifier).setValue(value.first.path); - ref.read(routerProvider).go(RoutesPaths.bookmarks); - } - }, - onError: (e, stackTrace) => Sentry.captureException(e, stackTrace: stackTrace), - ); - - ReceiveSharingIntent.instance.getInitialMedia().then( - (value) { - if (value.isNotEmpty && - (value.first.type == SharedMediaType.url || (value.first.type == SharedMediaType.text))) { - ref.read(receiveSharingIntentUrlProvider.notifier).setValue(value.first.path); - ref.read(routerProvider).go(RoutesPaths.bookmarks); - ReceiveSharingIntent.instance.reset(); - } - }, - onError: (e, stackTrace) => Sentry.captureException(e, stackTrace: stackTrace), - ); - } - - @override - Widget build(BuildContext context) { - final selectedColor = ref.watch(appStatusProvider).selectedColor; - final useDynamicColor = ref.watch(appStatusProvider).useDynamicTheme; - - return DynamicColorBuilder( - builder: (lightDynamic, darkDynamic) { - ref.read(appStatusProvider.notifier).setSupportsDynamicTheme(lightDynamic != null && darkDynamic != null); - return MaterialApp.router( - title: 'Linkdy', - theme: lightDynamic != null - ? useDynamicColor == true - ? lightTheme(lightDynamic) - : lightThemeOldVersions(colors[selectedColor]) - : lightThemeOldVersions(colors[selectedColor]), - darkTheme: darkDynamic != null - ? useDynamicColor == true - ? darkTheme(darkDynamic) - : darkThemeOldVersions(colors[selectedColor]) - : darkThemeOldVersions(colors[selectedColor]), - themeMode: ref.watch(selectedThemeProvider), - locale: TranslationProvider.of(context).flutterLocale, - supportedLocales: AppLocaleUtils.supportedLocales, - localizationsDelegates: GlobalMaterialLocalizations.delegates, - debugShowCheckedModeBanner: false, - scaffoldMessengerKey: ScaffoldMessengerKeys.root, - routerConfig: ref.watch(routerProvider), - ); - }, - ); - } -} diff --git a/lib/models/api_response.dart b/lib/models/api_response.dart deleted file mode 100644 index 2df8b72..0000000 --- a/lib/models/api_response.dart +++ /dev/null @@ -1,11 +0,0 @@ -class ApiResponse { - final bool successful; - final T? content; - final int? statusCode; - - const ApiResponse({ - required this.successful, - this.content, - this.statusCode, - }); -} diff --git a/lib/models/app_route.dart b/lib/models/app_route.dart deleted file mode 100644 index 2283b87..0000000 --- a/lib/models/app_route.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter/material.dart'; - -class AppRoute { - final IconData icon; - final String route; - final String name; - - const AppRoute({ - required this.icon, - required this.route, - required this.name, - }); -} diff --git a/lib/models/data/bookmarks.dart b/lib/models/data/bookmarks.dart deleted file mode 100644 index 9d8cba2..0000000 --- a/lib/models/data/bookmarks.dart +++ /dev/null @@ -1,122 +0,0 @@ -class BookmarksResponse { - final int? count; - final String? next; - final String? previous; - final List? results; - - BookmarksResponse({ - this.count, - this.next, - this.previous, - this.results, - }); - - factory BookmarksResponse.fromJson(Map json) => BookmarksResponse( - count: json["count"], - next: json["next"], - previous: json["previous"], - results: json["results"] == null ? [] : List.from(json["results"]!.map((x) => Bookmark.fromJson(x))), - ); - - Map toJson() => { - "count": count, - "next": next, - "previous": previous, - "results": results == null ? [] : List.from(results!.map((x) => x.toJson())), - }; -} - -class Bookmark { - final int? id; - final String? url; - final String? title; - final String? description; - final String? notes; - final String? websiteTitle; - final String? websiteDescription; - final bool? isArchived; - final bool? unread; - final bool? shared; - final List? tagNames; - final DateTime? dateAdded; - final DateTime? dateModified; - - Bookmark({ - this.id, - this.url, - this.title, - this.description, - this.notes, - this.websiteTitle, - this.websiteDescription, - this.isArchived, - this.unread, - this.shared, - this.tagNames, - this.dateAdded, - this.dateModified, - }); - - factory Bookmark.fromJson(Map json) => Bookmark( - id: json["id"], - url: json["url"], - title: json["title"], - description: json["description"], - notes: json["notes"], - websiteTitle: json["website_title"], - websiteDescription: json["website_description"], - isArchived: json["is_archived"], - unread: json["unread"], - shared: json["shared"], - tagNames: json["tag_names"] == null ? [] : List.from(json["tag_names"]!.map((x) => x)), - dateAdded: json["date_added"] == null ? null : DateTime.parse(json["date_added"]), - dateModified: json["date_modified"] == null ? null : DateTime.parse(json["date_modified"]), - ); - - Map toJson() => { - "id": id, - "url": url, - "title": title, - "description": description, - "notes": notes, - "website_title": websiteTitle, - "website_description": websiteDescription, - "is_archived": isArchived, - "unread": unread, - "shared": shared, - "tag_names": tagNames == null ? [] : List.from(tagNames!.map((x) => x)), - "date_added": dateAdded?.toIso8601String(), - "date_modified": dateModified?.toIso8601String(), - }; - - Bookmark copyWith({ - int? id, - String? url, - String? title, - String? description, - String? notes, - String? websiteTitle, - String? websiteDescription, - bool? isArchived, - bool? unread, - bool? shared, - List? tagNames, - DateTime? dateAdded, - DateTime? dateModified, - }) => - Bookmark( - id: id ?? this.id, - url: url ?? this.url, - title: title ?? this.title, - description: description ?? this.description, - notes: notes ?? this.notes, - websiteTitle: websiteTitle ?? this.websiteTitle, - websiteDescription: websiteDescription ?? this.websiteDescription, - isArchived: isArchived ?? this.isArchived, - unread: unread ?? this.unread, - shared: shared ?? this.shared, - tagNames: tagNames ?? this.tagNames, - dateAdded: dateAdded ?? this.dateAdded, - dateModified: dateModified ?? this.dateModified, - ); -} diff --git a/lib/models/data/check_bookmark.dart b/lib/models/data/check_bookmark.dart deleted file mode 100644 index 73028f7..0000000 --- a/lib/models/data/check_bookmark.dart +++ /dev/null @@ -1,45 +0,0 @@ -import 'package:linkdy/models/data/bookmarks.dart'; - -class CheckBookmark { - final Bookmark? bookmark; - final Metadata? metadata; - - CheckBookmark({ - this.bookmark, - this.metadata, - }); - - factory CheckBookmark.fromJson(Map json) => CheckBookmark( - bookmark: json["bookmark"] != null ? Bookmark.fromJson(json["bookmark"]) : null, - metadata: json["metadata"] == null ? null : Metadata.fromJson(json["metadata"]), - ); - - Map toJson() => { - "bookmark": bookmark?.toJson(), - "metadata": metadata?.toJson(), - }; -} - -class Metadata { - final String? url; - final String? title; - final String? description; - - Metadata({ - this.url, - this.title, - this.description, - }); - - factory Metadata.fromJson(Map json) => Metadata( - url: json["url"], - title: json["title"], - description: json["description"], - ); - - Map toJson() => { - "url": url, - "title": title, - "description": description, - }; -} diff --git a/lib/models/data/patch_bookmark_data.dart b/lib/models/data/patch_bookmark_data.dart deleted file mode 100644 index 43675ae..0000000 --- a/lib/models/data/patch_bookmark_data.dart +++ /dev/null @@ -1,50 +0,0 @@ -class PatchBookmarkData { - final String? url; - final String? title; - final String? description; - final bool? isArchived; - final bool? unread; - final bool? shared; - final String? tagNames; - final String? notes; - - const PatchBookmarkData({ - this.url, - this.title, - this.description, - this.isArchived, - this.unread, - this.shared, - this.tagNames, - this.notes, - }); - - Map toJson() { - Map ret = {}; - if (url != null) { - ret = {...ret, "url": url}; - } - if (title != null) { - ret = {...ret, "title": title}; - } - if (description != null) { - ret = {...ret, "description": description}; - } - if (isArchived != null) { - ret = {...ret, "is_archived": isArchived}; - } - if (unread != null) { - ret = {...ret, "unread": unread}; - } - if (shared != null) { - ret = {...ret, "shared": shared}; - } - if (notes != null) { - ret = {...ret, "notes": notes}; - } - if (tagNames != null) { - ret = {...ret, "notag_namestes": tagNames}; - } - return ret; - } -} diff --git a/lib/models/data/set_bookmark_data.dart b/lib/models/data/set_bookmark_data.dart deleted file mode 100644 index 793d76e..0000000 --- a/lib/models/data/set_bookmark_data.dart +++ /dev/null @@ -1,40 +0,0 @@ -class SetBookmarkData { - final String url; - final String title; - final String description; - final bool isArchived; - final bool unread; - final bool shared; - final String tagNames; - final String notes; - - const SetBookmarkData({ - required this.url, - required this.title, - required this.description, - required this.isArchived, - required this.unread, - required this.shared, - required this.tagNames, - required this.notes, - }); - - Map toJson() { - Map ret = { - "url": url, - "title": title, - "description": description, - "is_archived": isArchived, - "unread": unread, - "shared": shared, - "notes": notes, - }; - if (tagNames != "") { - ret = { - ...ret, - "tag_names": tagNames, - }; - } - return ret; - } -} diff --git a/lib/models/data/tag_bookmarks.dart b/lib/models/data/tag_bookmarks.dart deleted file mode 100644 index 0b8fc0e..0000000 --- a/lib/models/data/tag_bookmarks.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/models/data/tags.dart'; - -class TagBookmarksResponse { - final BookmarksResponse? bookmarksResponse; - final Tag? tag; - - const TagBookmarksResponse({ - required this.bookmarksResponse, - required this.tag, - }); -} diff --git a/lib/models/data/tags.dart b/lib/models/data/tags.dart deleted file mode 100644 index 74c6379..0000000 --- a/lib/models/data/tags.dart +++ /dev/null @@ -1,51 +0,0 @@ -class TagsResponse { - final int? count; - final String? next; - final String? previous; - final List? results; - - TagsResponse({ - this.count, - this.next, - this.previous, - this.results, - }); - - factory TagsResponse.fromJson(Map json) => TagsResponse( - count: json["count"], - next: json["next"], - previous: json["previous"], - results: json["results"] == null ? [] : List.from(json["results"]!.map((x) => Tag.fromJson(x))), - ); - - Map toJson() => { - "count": count, - "next": next, - "previous": previous, - "results": results == null ? [] : List.from(results!.map((x) => x.toJson())), - }; -} - -class Tag { - final int? id; - final String? name; - final DateTime? dateAdded; - - Tag({ - this.id, - this.name, - this.dateAdded, - }); - - factory Tag.fromJson(Map json) => Tag( - id: json["id"], - name: json["name"], - dateAdded: json["date_added"] == null ? null : DateTime.parse(json["date_added"]), - ); - - Map toJson() => { - "id": id, - "name": name, - "date_added": dateAdded?.toIso8601String(), - }; -} diff --git a/lib/models/favicon_item.dart b/lib/models/favicon_item.dart deleted file mode 100644 index 12b2c20..0000000 --- a/lib/models/favicon_item.dart +++ /dev/null @@ -1,11 +0,0 @@ -class FaviconItem { - final String url; - final String favicon; - final bool isSvg; - - const FaviconItem({ - required this.url, - required this.favicon, - required this.isSvg, - }); -} diff --git a/lib/models/providers_models/app_status.model.dart b/lib/models/providers_models/app_status.model.dart deleted file mode 100644 index b01ada8..0000000 --- a/lib/models/providers_models/app_status.model.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:linkdy/constants/enums.dart'; - -class AppStatusModel { - SelectedTheme selectedTheme; - bool supportsDynamicTheme; - bool useDynamicTheme; - int selectedColor; - OpenLinksBrowser openLinksBrowser; - bool showFavicon; - List defaultTags; - bool markAsUnreadDefault; - bool enableSlideOptions; - - AppStatusModel({ - this.selectedTheme = SelectedTheme.system, - this.supportsDynamicTheme = false, - this.useDynamicTheme = true, - this.selectedColor = 0, - this.openLinksBrowser = OpenLinksBrowser.integrated, - this.showFavicon = true, - required this.defaultTags, - this.markAsUnreadDefault = false, - this.enableSlideOptions = true, - }); -} diff --git a/lib/models/providers_models/snackbar_status.model.dart b/lib/models/providers_models/snackbar_status.model.dart deleted file mode 100644 index 8caaaa7..0000000 --- a/lib/models/providers_models/snackbar_status.model.dart +++ /dev/null @@ -1,7 +0,0 @@ -class SnackbarStatusModel { - bool visible; - - SnackbarStatusModel({ - this.visible = false, - }); -} diff --git a/lib/models/received_sharing_intent.dart b/lib/models/received_sharing_intent.dart deleted file mode 100644 index b09e06a..0000000 --- a/lib/models/received_sharing_intent.dart +++ /dev/null @@ -1,5 +0,0 @@ -class ReceivedSharingIntentModel { - bool processed; - - ReceivedSharingIntentModel({this.processed = false}); -} diff --git a/lib/models/server_instance.dart b/lib/models/server_instance.dart deleted file mode 100644 index 287f8a0..0000000 --- a/lib/models/server_instance.dart +++ /dev/null @@ -1,35 +0,0 @@ -class ServerInstance { - final String id; - final String method; - final String ipDomain; - final int? port; - final String? path; - final String token; - - const ServerInstance({ - required this.id, - required this.method, - required this.ipDomain, - this.port, - this.path, - required this.token, - }); - - factory ServerInstance.fromJson(Map data) => ServerInstance( - id: data['id'], - method: data['method'], - ipDomain: data['ipDomain'], - port: data['port'], - path: data['path'], - token: data['token'], - ); - - Map toJson() => { - "id": id, - "method": method, - "ipDomain": ipDomain, - "port": port, - "path": path, - "token": token, - }; -} diff --git a/lib/providers/api_client.provider.dart b/lib/providers/api_client.provider.dart deleted file mode 100644 index a8025ba..0000000 --- a/lib/providers/api_client.provider.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:dio/dio.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/providers/server_instances.provider.dart'; -import 'package:linkdy/providers/dio_interceptor.provider.dart'; -import 'package:linkdy/services/api_client.dart'; -import 'package:linkdy/utils/api_base_url.dart'; - -part 'api_client.provider.g.dart'; - -@Riverpod(keepAlive: true) -class ApiClient extends _$ApiClient { - @override - ApiClientService? build() { - final savedInstances = ref.watch(serverInstancesProvider); - if (savedInstances.isNotEmpty) { - final instance = savedInstances[0]; - final dio = Dio( - BaseOptions( - baseUrl: apiBaseUrl(instance), - headers: { - "Authorization": "Token ${instance.token}", - }, - ), - )..interceptors.add(ref.watch(dioInterceptorProvider)); - return ApiClientService( - serverInstance: instance, - dioInstance: dio, - ); - } - return null; - } - - void setApiClient(ApiClientService client) { - state = client; - } - - void disconnectApiClient() { - state = null; - ref.read(serverInstancesProvider.notifier).removeServerInstances(); - } -} diff --git a/lib/providers/api_client.provider.g.dart b/lib/providers/api_client.provider.g.dart deleted file mode 100644 index 780fcf0..0000000 --- a/lib/providers/api_client.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'api_client.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$apiClientHash() => r'81e911e24bda3baf158a7d583271c4467821b11f'; - -/// See also [ApiClient]. -@ProviderFor(ApiClient) -final apiClientProvider = - NotifierProvider.internal( - ApiClient.new, - name: r'apiClientProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$apiClientHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$ApiClient = Notifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/app_info.provider.dart b/lib/providers/app_info.provider.dart deleted file mode 100644 index a0a38bf..0000000 --- a/lib/providers/app_info.provider.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:package_info_plus/package_info_plus.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'app_info.provider.g.dart'; - -@Riverpod(keepAlive: true) -PackageInfo appInfo(AppInfoRef ref) { - throw UnimplementedError(); -} diff --git a/lib/providers/app_info.provider.g.dart b/lib/providers/app_info.provider.g.dart deleted file mode 100644 index bfe578a..0000000 --- a/lib/providers/app_info.provider.g.dart +++ /dev/null @@ -1,24 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'app_info.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$appInfoHash() => r'c1b99fe8e0ba1b1ba04aa2c1ae066a3de9f1dac1'; - -/// See also [appInfo]. -@ProviderFor(appInfo) -final appInfoProvider = Provider.internal( - appInfo, - name: r'appInfoProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$appInfoHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef AppInfoRef = ProviderRef; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/app_status.provider.dart b/lib/providers/app_status.provider.dart deleted file mode 100644 index dc34b22..0000000 --- a/lib/providers/app_status.provider.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/constants/shared_preferences_keys.dart'; -import 'package:linkdy/providers/shared_preferences.provider.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/providers_models/app_status.model.dart'; - -part 'app_status.provider.g.dart'; - -@Riverpod(keepAlive: true) -class AppStatus extends _$AppStatus { - @override - AppStatusModel build() { - final sharedPreferences = ref.watch(sharedPreferencesProvider); - return AppStatusModel( - selectedColor: sharedPreferences.getInt(SharedPreferencesKeys.selectedColor) ?? 0, - selectedTheme: SelectedTheme.values[sharedPreferences.getInt(SharedPreferencesKeys.selectedTheme) ?? 0], - useDynamicTheme: sharedPreferences.getBool(SharedPreferencesKeys.useDynamicTheme) ?? true, - openLinksBrowser: - OpenLinksBrowserExtension.fromString(sharedPreferences.getString(SharedPreferencesKeys.openLinksBrowser)) ?? - OpenLinksBrowser.integrated, - showFavicon: sharedPreferences.getBool(SharedPreferencesKeys.showFavicon) ?? true, - defaultTags: sharedPreferences.getStringList(SharedPreferencesKeys.defaultTags) ?? [], - markAsUnreadDefault: sharedPreferences.getBool(SharedPreferencesKeys.markAsUnreadDefault) ?? false, - enableSlideOptions: sharedPreferences.getBool(SharedPreferencesKeys.enableSlideOptions) ?? true, - ); - } - - void setTheme(SelectedTheme theme) { - state.selectedTheme = theme; - ref.read(sharedPreferencesProvider).setInt(SharedPreferencesKeys.selectedTheme, theme.index); - ref.notifyListeners(); - } - - void setSupportsDynamicTheme(bool value) { - state.supportsDynamicTheme = value; - } - - void setUseDynamicTheme(bool value) { - state.useDynamicTheme = value; - ref.read(sharedPreferencesProvider).setBool(SharedPreferencesKeys.useDynamicTheme, value); - ref.notifyListeners(); - } - - void setSelectedColor(int value) { - state.selectedColor = value; - ref.read(sharedPreferencesProvider).setInt(SharedPreferencesKeys.selectedColor, value); - ref.notifyListeners(); - } - - void updateSelectedBrowser(OpenLinksBrowser? value) { - if (value == null) return; - state.openLinksBrowser = value; - ref.read(sharedPreferencesProvider).setString(SharedPreferencesKeys.openLinksBrowser, value.toString()); - ref.notifyListeners(); - } - - void setShowFavicon(bool value) { - state.showFavicon = value; - ref.read(sharedPreferencesProvider).setBool(SharedPreferencesKeys.showFavicon, value); - ref.notifyListeners(); - } - - void addDefaultTag(String value) { - final newTags = [...state.defaultTags, value]; - state.defaultTags = newTags; - ref.read(sharedPreferencesProvider).setStringList(SharedPreferencesKeys.defaultTags, newTags); - ref.notifyListeners(); - } - - void removeDefaultTag(String value) { - final newTags = state.defaultTags.where((e) => e != value).toList(); - state.defaultTags = newTags; - ref.read(sharedPreferencesProvider).setStringList(SharedPreferencesKeys.defaultTags, newTags); - ref.notifyListeners(); - } - - void setMarkAsUnreadDefault(bool value) { - state.markAsUnreadDefault = value; - ref.read(sharedPreferencesProvider).setBool(SharedPreferencesKeys.markAsUnreadDefault, value); - ref.notifyListeners(); - } - - void setEnableSlideOptions(bool value) { - state.enableSlideOptions = value; - ref.read(sharedPreferencesProvider).setBool(SharedPreferencesKeys.enableSlideOptions, value); - ref.notifyListeners(); - } -} - -@riverpod -ThemeMode selectedTheme(SelectedThemeRef ref) { - switch (ref.watch(appStatusProvider).selectedTheme) { - case SelectedTheme.system: - return SchedulerBinding.instance.window.platformBrightness == Brightness.light ? ThemeMode.light : ThemeMode.dark; - - case SelectedTheme.light: - return ThemeMode.light; - - case SelectedTheme.dark: - return ThemeMode.dark; - } -} diff --git a/lib/providers/app_status.provider.g.dart b/lib/providers/app_status.provider.g.dart deleted file mode 100644 index bbe08ef..0000000 --- a/lib/providers/app_status.provider.g.dart +++ /dev/null @@ -1,39 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'app_status.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$selectedThemeHash() => r'b820484a59ed72419c5b4cad0b894a030b54c702'; - -/// See also [selectedTheme]. -@ProviderFor(selectedTheme) -final selectedThemeProvider = AutoDisposeProvider.internal( - selectedTheme, - name: r'selectedThemeProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$selectedThemeHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef SelectedThemeRef = AutoDisposeProviderRef; -String _$appStatusHash() => r'745dcff38d083afce16217c439f7667bda875a6d'; - -/// See also [AppStatus]. -@ProviderFor(AppStatus) -final appStatusProvider = NotifierProvider.internal( - AppStatus.new, - name: r'appStatusProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$appStatusHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$AppStatus = Notifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/dio_interceptor.provider.dart b/lib/providers/dio_interceptor.provider.dart deleted file mode 100644 index a8964f0..0000000 --- a/lib/providers/dio_interceptor.provider.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:dio/dio.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/utils/snackbar.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/providers/server_instances.provider.dart'; -import 'package:linkdy/router/routes.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -part 'dio_interceptor.provider.g.dart'; - -@Riverpod(keepAlive: true) -InterceptorsWrapper dioInterceptor(DioInterceptorRef ref) { - return InterceptorsWrapper( - onError: (error, handler) async { - if (error.response?.statusCode == 401) { - while (GoRouter.of(rootNavigatorKey.currentContext!).canPop() == true) { - GoRouter.of(rootNavigatorKey.currentContext!).pop(); - } - GoRouter.of(rootNavigatorKey.currentContext!).pushReplacement(RoutesPaths.onboarding); - ref.read(apiClientProvider.notifier).disconnectApiClient(); - ref.read(serverInstancesProvider.notifier).removeServerInstances(); - showSnackbar(key: ScaffoldMessengerKeys.root, label: t.generic.authTokenNotValid, color: Colors.red); - } - handler.next(error); - }, - ); -} diff --git a/lib/providers/dio_interceptor.provider.g.dart b/lib/providers/dio_interceptor.provider.g.dart deleted file mode 100644 index 802c82c..0000000 --- a/lib/providers/dio_interceptor.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'dio_interceptor.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$dioInterceptorHash() => r'16ba03ce5f4547c91566a38f348cf85df73fbfca'; - -/// See also [dioInterceptor]. -@ProviderFor(dioInterceptor) -final dioInterceptorProvider = Provider.internal( - dioInterceptor, - name: r'dioInterceptorProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$dioInterceptorHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef DioInterceptorRef = ProviderRef; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/receive_sharing_intent_url.provider.dart b/lib/providers/receive_sharing_intent_url.provider.dart deleted file mode 100644 index 740b613..0000000 --- a/lib/providers/receive_sharing_intent_url.provider.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'receive_sharing_intent_url.provider.g.dart'; - -@Riverpod(keepAlive: true) -class ReceiveSharingIntentUrl extends _$ReceiveSharingIntentUrl { - @override - String? build() { - return null; - } - - void setValue(String? value) { - state = value; - ref.notifyListeners(); - } -} diff --git a/lib/providers/receive_sharing_intent_url.provider.g.dart b/lib/providers/receive_sharing_intent_url.provider.g.dart deleted file mode 100644 index bbf1d4d..0000000 --- a/lib/providers/receive_sharing_intent_url.provider.g.dart +++ /dev/null @@ -1,27 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'receive_sharing_intent_url.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$receiveSharingIntentUrlHash() => - r'fc62c4867e311b7d8d0573d263af2daaf784fb1f'; - -/// See also [ReceiveSharingIntentUrl]. -@ProviderFor(ReceiveSharingIntentUrl) -final receiveSharingIntentUrlProvider = - NotifierProvider.internal( - ReceiveSharingIntentUrl.new, - name: r'receiveSharingIntentUrlProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$receiveSharingIntentUrlHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$ReceiveSharingIntentUrl = Notifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/router.provider.dart b/lib/providers/router.provider.dart deleted file mode 100644 index 4e7fd18..0000000 --- a/lib/providers/router.provider.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:go_router/go_router.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/router/routes.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -part 'router.provider.g.dart'; - -@Riverpod(keepAlive: true) -GoRouter router(RouterRef ref) { - return GoRouter( - redirect: (context, state) { - if (ref.watch(apiClientProvider) == null) { - return RoutesPaths.onboarding; - } - return null; - }, - initialLocation: RoutesPaths.bookmarks, - routes: appRoutes, - navigatorKey: rootNavigatorKey, - ); -} diff --git a/lib/providers/router.provider.g.dart b/lib/providers/router.provider.g.dart deleted file mode 100644 index 0224bc7..0000000 --- a/lib/providers/router.provider.g.dart +++ /dev/null @@ -1,24 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'router.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$routerHash() => r'63ab878a4f0eadb075a6d23d1e32a8d233fcf74e'; - -/// See also [router]. -@ProviderFor(router) -final routerProvider = Provider.internal( - router, - name: r'routerProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$routerHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef RouterRef = ProviderRef; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/server_instances.provider.dart b/lib/providers/server_instances.provider.dart deleted file mode 100644 index 90923bf..0000000 --- a/lib/providers/server_instances.provider.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'dart:convert'; - -import 'package:linkdy/constants/shared_preferences_keys.dart'; -import 'package:linkdy/providers/shared_preferences.provider.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/models/server_instance.dart'; - -part 'server_instances.provider.g.dart'; - -@Riverpod(keepAlive: true) -class ServerInstances extends _$ServerInstances { - @override - List build() { - final instances = ref.watch(sharedPreferencesProvider).getStringList(SharedPreferencesKeys.serversInstances); - - if (instances == null) return []; - - List generatedInstances = []; - for (final instance in instances) { - try { - generatedInstances.add(ServerInstance.fromJson(jsonDecode(instance))); - } catch (_) {/* IF ERROR OMIT */} - } - - return generatedInstances; - } - - ServerInstance? getInstance(String id) { - try { - return state.firstWhere((instance) => instance.id == id); - } catch (_) { - return null; - } - } - - void saveNewInstance(ServerInstance instance) { - state = [instance]; - saveServerInstances([instance]); - } - - void saveServerInstances(List instances) async { - final stringList = instances.map((i) => jsonEncode(i.toJson())).toList(); - ref.read(sharedPreferencesProvider).setStringList(SharedPreferencesKeys.serversInstances, stringList); - } - - void removeServerInstances() { - state = []; - ref.read(sharedPreferencesProvider).remove(SharedPreferencesKeys.serversInstances); - } -} diff --git a/lib/providers/server_instances.provider.g.dart b/lib/providers/server_instances.provider.g.dart deleted file mode 100644 index 3339cec..0000000 --- a/lib/providers/server_instances.provider.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'server_instances.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$serverInstancesHash() => r'ee41f5a717b9f779aa4319cc711b479a47c1c9ef'; - -/// See also [ServerInstances]. -@ProviderFor(ServerInstances) -final serverInstancesProvider = - NotifierProvider>.internal( - ServerInstances.new, - name: r'serverInstancesProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$serverInstancesHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$ServerInstances = Notifier>; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/providers/shared_preferences.provider.dart b/lib/providers/shared_preferences.provider.dart deleted file mode 100644 index 6a2abe7..0000000 --- a/lib/providers/shared_preferences.provider.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -part 'shared_preferences.provider.g.dart'; - -@Riverpod(keepAlive: true) -SharedPreferences sharedPreferences(SharedPreferencesRef ref) { - throw UnimplementedError(); -} diff --git a/lib/providers/shared_preferences.provider.g.dart b/lib/providers/shared_preferences.provider.g.dart deleted file mode 100644 index c097469..0000000 --- a/lib/providers/shared_preferences.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'shared_preferences.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$sharedPreferencesHash() => r'3a9f8412df34c1653d08100c9826aa2125b80f7f'; - -/// See also [sharedPreferences]. -@ProviderFor(sharedPreferences) -final sharedPreferencesProvider = Provider.internal( - sharedPreferences, - name: r'sharedPreferencesProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$sharedPreferencesHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef SharedPreferencesRef = ProviderRef; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/router/names.dart b/lib/router/names.dart deleted file mode 100644 index 3775fcf..0000000 --- a/lib/router/names.dart +++ /dev/null @@ -1,3 +0,0 @@ -class RoutesNames { - static const tagBookmarks = "tagBookmarks"; -} diff --git a/lib/router/paths.dart b/lib/router/paths.dart deleted file mode 100644 index 007c4f3..0000000 --- a/lib/router/paths.dart +++ /dev/null @@ -1,14 +0,0 @@ -class RoutesPaths { - static const onboarding = "/onboarding"; - static const bookmarks = "/bookmarks"; - static const bookmarksSearch = "/bookmarks/search"; - static const webview = "/webview"; - static const tags = "/tags"; - static const tagBookmarks = "/tags/:id"; - static const sharedBookmarks = "/bookmarks/shared"; - static const archivedBookmarks = "/bookmarks/archived"; - static const settings = "/settings"; - static const customization = "/settings/customization"; - static const defaultTags = "/settings/default-tags"; - static const generalSettings = "/settings/general"; -} diff --git a/lib/router/routes.dart b/lib/router/routes.dart deleted file mode 100644 index 3929f54..0000000 --- a/lib/router/routes.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:linkdy/router/names.dart'; - -import 'package:linkdy/screens/bookmarks/ui/bookmarks.dart'; -import 'package:linkdy/screens/onboarding/ui/onboarding.dart'; -import 'package:linkdy/screens/settings/ui/customization/customization.dart'; -import 'package:linkdy/screens/settings/ui/default_tags/default_tags.dart'; -import 'package:linkdy/screens/settings/ui/general_settings/general_settings.dart'; -import 'package:linkdy/screens/settings/ui/settings.dart'; -import 'package:linkdy/screens/filtered_bookmarks/ui/filtered_bookmarks.dart'; -import 'package:linkdy/screens/tags/ui/tags.dart'; -import 'package:linkdy/screens/webview/ui/webview.dart'; -import 'package:linkdy/widgets/page_transition.dart'; - -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/data/tags.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/router/paths.dart'; - -final rootNavigatorKey = GlobalKey(); -final linksNavigatorKey = GlobalKey(); -final searchNavigatorKey = GlobalKey(); -final settingsNavigatorKey = GlobalKey(); - -final List appRoutes = [ - GoRoute( - path: RoutesPaths.onboarding, - builder: (context, state) => const Onboarding(), - ), - GoRoute( - path: RoutesPaths.bookmarks, - builder: (context, state) => const PageTransition(child: BookmarksScreen()), - ), - GoRoute( - path: RoutesPaths.tags, - builder: (context, state) => const PageTransition(child: TagsScreen()), - ), - GoRoute( - path: RoutesPaths.settings, - builder: (context, state) => const PageTransition(child: SettingsScreen()), - ), - GoRoute( - path: RoutesPaths.tagBookmarks, - name: RoutesNames.tagBookmarks, - builder: (context, state) => FilteredBookmarksScreen( - filteredBookmarksMode: FilteredBookmarksMode.tag, - tagId: state.pathParameters['id'], - tag: state.extra as Tag?, - ), - ), - GoRoute( - path: RoutesPaths.sharedBookmarks, - builder: (context, state) => const FilteredBookmarksScreen(filteredBookmarksMode: FilteredBookmarksMode.shared), - ), - GoRoute( - path: RoutesPaths.archivedBookmarks, - builder: (context, state) => const FilteredBookmarksScreen(filteredBookmarksMode: FilteredBookmarksMode.archived), - ), - GoRoute( - path: RoutesPaths.customization, - builder: (context, state) => const Customization(), - ), - GoRoute( - path: RoutesPaths.defaultTags, - builder: (context, state) => const DefaultTagsScreen(), - ), - GoRoute( - path: RoutesPaths.generalSettings, - builder: (context, state) => const GeneralSettings(), - ), - GoRoute( - path: RoutesPaths.webview, - builder: (context, state) => WebViewScreen(bookmark: state.extra as Bookmark), - ), -]; diff --git a/lib/screens/bookmarks/model/bookmark_form.model.dart b/lib/screens/bookmarks/model/bookmark_form.model.dart deleted file mode 100644 index dcfaa9c..0000000 --- a/lib/screens/bookmarks/model/bookmark_form.model.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:linkdy/constants/enums.dart'; - -class BookmarkFormModel { - final TextEditingController urlController; - String? urlError; - bool? bookmarkValid; - LoadStatus? checkBookmarkLoadStatus; - final TextEditingController titleController; - final TextEditingController descriptionController; - bool markAsUnread; - final TextEditingController tagsController; - String? tagsError; - List tags; - final TextEditingController notesController; - int? editBookmarkId; - bool share; - bool bookmarkExists = false; - - BookmarkFormModel({ - required this.urlController, - this.urlError, - this.bookmarkValid, - this.checkBookmarkLoadStatus, - required this.titleController, - required this.descriptionController, - this.markAsUnread = false, - required this.tagsController, - this.tagsError, - required this.tags, - required this.notesController, - this.editBookmarkId, - this.share = false, - }); -} diff --git a/lib/screens/bookmarks/model/bookmarks.model.dart b/lib/screens/bookmarks/model/bookmarks.model.dart deleted file mode 100644 index deba735..0000000 --- a/lib/screens/bookmarks/model/bookmarks.model.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:go_router/go_router.dart'; - -import 'package:linkdy/config/options.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; - -class BookmarksModel { - int currentPage; - int limit; - List bookmarks; - LoadStatus inialLoadStatus; - bool loadingMore; - int maxNumber; - ReadStatus readStatus; - Bookmark? selectedBookmark; - final GoRouter webViewRouter; - SortingType sortingType; - SortingWay sortingWay; - - BookmarksModel({ - this.currentPage = 0, - this.limit = ConfigOptions.listLimit, - required this.bookmarks, - this.inialLoadStatus = LoadStatus.loading, - this.loadingMore = false, - this.maxNumber = 0, - this.readStatus = ReadStatus.all, - this.selectedBookmark, - required this.webViewRouter, - this.sortingType = SortingType.date, - this.sortingWay = SortingWay.descendant, - }); -} diff --git a/lib/screens/bookmarks/model/favicon_loader.model.dart b/lib/screens/bookmarks/model/favicon_loader.model.dart deleted file mode 100644 index 4481255..0000000 --- a/lib/screens/bookmarks/model/favicon_loader.model.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:linkdy/models/favicon_item.dart'; - -class FaviconLoaderModel { - List favicons; - bool loadingFavicons; - - FaviconLoaderModel({ - required this.favicons, - this.loadingFavicons = false, - }); -} diff --git a/lib/screens/bookmarks/model/search_bookmarks.model.dart b/lib/screens/bookmarks/model/search_bookmarks.model.dart deleted file mode 100644 index c2684a5..0000000 --- a/lib/screens/bookmarks/model/search_bookmarks.model.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -import 'package:linkdy/config/options.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; - -class SearchBookmarksModel { - final TextEditingController searchController; - String? searchTerm; - int currentPage; - int limit; - List bookmarks; - LoadStatus inialLoadStatus; - bool loadingMore; - int maxNumber; - Bookmark? selectedBookmark; - final GoRouter webViewRouter; - - SearchBookmarksModel({ - required this.searchController, - this.searchTerm = "", - this.currentPage = 0, - this.limit = ConfigOptions.listLimit, - required this.bookmarks, - this.inialLoadStatus = LoadStatus.loaded, - this.loadingMore = false, - this.maxNumber = 0, - this.selectedBookmark, - required this.webViewRouter, - }); -} diff --git a/lib/screens/bookmarks/provider/bookmark_form.provider.dart b/lib/screens/bookmarks/provider/bookmark_form.provider.dart deleted file mode 100644 index 87319c4..0000000 --- a/lib/screens/bookmarks/provider/bookmark_form.provider.dart +++ /dev/null @@ -1,195 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/screens/bookmarks/model/bookmark_form.model.dart'; - -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/utils/snackbar.dart'; -import 'package:linkdy/models/data/tags.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/utils/process_modal.dart'; -import 'package:linkdy/models/data/set_bookmark_data.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/constants/regexp.dart'; -import 'package:linkdy/models/api_response.dart'; -import 'package:linkdy/models/data/check_bookmark.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -part 'bookmark_form.provider.g.dart'; - -@riverpod -Future> checkBookmark(CheckBookmarkRef ref, String url) async { - final result = await ref.watch(apiClientProvider)!.fetchCheckAddBookmark(url: url); - return result; -} - -@riverpod -FutureOr> getTags(GetTagsRef ref) async { - final result = await ref.watch(apiClientProvider)!.fetchTags(); - return result; -} - -@riverpod -class BookmarkForm extends _$BookmarkForm { - @override - BookmarkFormModel build() { - return BookmarkFormModel( - urlController: TextEditingController(), - titleController: TextEditingController(), - descriptionController: TextEditingController(), - tagsController: TextEditingController(), - tags: [], - notesController: TextEditingController(), - markAsUnread: ref.read(appStatusProvider).markAsUnreadDefault, - ); - } - - void initializeProvider(Bookmark bookmark) { - state.editBookmarkId = bookmark.id; - state.bookmarkValid = true; - state.checkBookmarkLoadStatus = LoadStatus.loaded; - state.urlController.text = bookmark.url ?? ''; - state.titleController.text = bookmark.title ?? ''; - state.descriptionController.text = bookmark.description ?? ''; - state.tags = bookmark.tagNames ?? []; - state.notesController.text = bookmark.notes ?? ''; - state.markAsUnread = bookmark.unread ?? ref.read(appStatusProvider).markAsUnreadDefault; - state.share = bookmark.shared ?? false; - } - - void initializeProviderUrl(String url) { - try { - final decoded = Uri.decodeComponent(url); - var value = decoded.contains(":~:text=") ? decoded.split(":~:text=")[1] : null; - state.urlController.text = value ?? decoded; - if (Regexps.urlWithoutProtocol.hasMatch(value ?? decoded)) { - state.urlError = null; - checkUrlDetails(updateState: false); - } else { - state.urlError = t.bookmarks.addBookmark.invalidUrl; - } - } catch (e) { - state.urlController.text = url; - state.urlError = t.bookmarks.addBookmark.invalidUrl; - ref.notifyListeners(); - } - } - - void validateUrl(String value) { - state.bookmarkValid = null; - state.checkBookmarkLoadStatus = null; - if (Regexps.urlWithoutProtocol.hasMatch(value)) { - state.urlError = null; - ref.notifyListeners(); - } else { - state.urlError = t.bookmarks.addBookmark.invalidUrl; - ref.notifyListeners(); - } - } - - void checkUrlDetails({required bool updateState}) async { - if (state.urlError == null && state.urlController.text != "") { - state.checkBookmarkLoadStatus = LoadStatus.loading; - state.bookmarkValid = null; - if (updateState == true) { - ref.notifyListeners(); - } - final result = await ref.read(checkBookmarkProvider(state.urlController.text).future); - if (result.successful == true) { - if (result.content?.bookmark != null) { - state.titleController.text = result.content?.bookmark?.title ?? ""; - state.descriptionController.text = result.content?.metadata?.description ?? ""; - state.tags = result.content?.bookmark?.tagNames ?? []; - state.notesController.text = result.content?.bookmark?.notes ?? ""; - state.markAsUnread = result.content?.bookmark?.unread ?? ref.read(appStatusProvider).markAsUnreadDefault; - state.share = result.content?.bookmark?.shared ?? false; - state.bookmarkExists = true; - } else { - state.titleController.text = result.content?.metadata?.title ?? ""; - state.descriptionController.text = result.content?.metadata?.description ?? ""; - } - state.bookmarkValid = true; - state.checkBookmarkLoadStatus = LoadStatus.loaded; - } else { - // URL check failed (e.g., authenticated URLs), but if URL format is valid, - // allow saving anyway since Linkding accepts these URLs - state.checkBookmarkLoadStatus = LoadStatus.error; - if (state.urlError == null) { - state.bookmarkValid = true; - } - } - ref.notifyListeners(); - } - } - - void updateMarkAsUnread(bool value) { - state.markAsUnread = value; - ref.notifyListeners(); - } - - void updateShare(bool value) { - state.share = value; - ref.notifyListeners(); - } - - void saveBookmark() async { - final newBookmark = SetBookmarkData( - url: state.urlController.text, - title: state.titleController.text, - description: state.descriptionController.text, - isArchived: false, - unread: state.markAsUnread, - shared: state.share, - tagNames: state.tags.join(","), - notes: state.notesController.text, - ); - - final processModal = ProcessModal(); - processModal.open(t.bookmarks.addBookmark.savingBookmark); - - final result = state.editBookmarkId != null - ? await ref.watch(apiClientProvider)!.putUpdateBookmark(state.editBookmarkId!, newBookmark) - : await ref.watch(apiClientProvider)!.postBookmark(newBookmark); - - processModal.close(); - - if (result.successful == true) { - ref.read(bookmarksProvider.notifier).refresh(); - ref.watch(routerProvider).pop(); - showSnackbar( - key: ScaffoldMessengerKeys.bookmarks, - label: t.bookmarks.addBookmark.bookmarkSavedSuccessfully, - color: Colors.green, - ); - } else { - showSnackbar( - key: ScaffoldMessengerKeys.addBookmark, - label: t.bookmarks.addBookmark.errorSavingBookmark, - color: Colors.red, - ); - } - } - - void validateTagInput(String value) { - if (value.contains(" ")) { - state.tagsError = t.bookmarks.addBookmark.tagNoWhitespaces; - } else { - state.tagsError = null; - } - ref.notifyListeners(); - } - - void setTags(List tags) { - state.tags = tags; - ref.notifyListeners(); - } - - void clearTagsController() { - state.tagsController.clear(); - ref.notifyListeners(); - } -} diff --git a/lib/screens/bookmarks/provider/bookmark_form.provider.g.dart b/lib/screens/bookmarks/provider/bookmark_form.provider.g.dart deleted file mode 100644 index 66f7ffb..0000000 --- a/lib/screens/bookmarks/provider/bookmark_form.provider.g.dart +++ /dev/null @@ -1,194 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'bookmark_form.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$checkBookmarkHash() => r'8eeb8cb7ee801ca7ed1b604b56a4301a86568c54'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -/// See also [checkBookmark]. -@ProviderFor(checkBookmark) -const checkBookmarkProvider = CheckBookmarkFamily(); - -/// See also [checkBookmark]. -class CheckBookmarkFamily - extends Family>> { - /// See also [checkBookmark]. - const CheckBookmarkFamily(); - - /// See also [checkBookmark]. - CheckBookmarkProvider call( - String url, - ) { - return CheckBookmarkProvider( - url, - ); - } - - @override - CheckBookmarkProvider getProviderOverride( - covariant CheckBookmarkProvider provider, - ) { - return call( - provider.url, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'checkBookmarkProvider'; -} - -/// See also [checkBookmark]. -class CheckBookmarkProvider - extends AutoDisposeFutureProvider> { - /// See also [checkBookmark]. - CheckBookmarkProvider( - String url, - ) : this._internal( - (ref) => checkBookmark( - ref as CheckBookmarkRef, - url, - ), - from: checkBookmarkProvider, - name: r'checkBookmarkProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$checkBookmarkHash, - dependencies: CheckBookmarkFamily._dependencies, - allTransitiveDependencies: - CheckBookmarkFamily._allTransitiveDependencies, - url: url, - ); - - CheckBookmarkProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.url, - }) : super.internal(); - - final String url; - - @override - Override overrideWith( - FutureOr> Function(CheckBookmarkRef provider) - create, - ) { - return ProviderOverride( - origin: this, - override: CheckBookmarkProvider._internal( - (ref) => create(ref as CheckBookmarkRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - url: url, - ), - ); - } - - @override - AutoDisposeFutureProviderElement> createElement() { - return _CheckBookmarkProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is CheckBookmarkProvider && other.url == url; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, url.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin CheckBookmarkRef - on AutoDisposeFutureProviderRef> { - /// The parameter `url` of this provider. - String get url; -} - -class _CheckBookmarkProviderElement - extends AutoDisposeFutureProviderElement> - with CheckBookmarkRef { - _CheckBookmarkProviderElement(super.provider); - - @override - String get url => (origin as CheckBookmarkProvider).url; -} - -String _$getTagsHash() => r'16138d28ed9ee5b99f5c84935f7a1eb98fad2a3b'; - -/// See also [getTags]. -@ProviderFor(getTags) -final getTagsProvider = - AutoDisposeFutureProvider>.internal( - getTags, - name: r'getTagsProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$getTagsHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef GetTagsRef = AutoDisposeFutureProviderRef>; -String _$bookmarkFormHash() => r'9d99362f0234456b26e4ef16179455862b300fe4'; - -/// See also [BookmarkForm]. -@ProviderFor(BookmarkForm) -final bookmarkFormProvider = - AutoDisposeNotifierProvider.internal( - BookmarkForm.new, - name: r'bookmarkFormProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$bookmarkFormHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$BookmarkForm = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/bookmarks/provider/bookmarks.provider.dart b/lib/screens/bookmarks/provider/bookmarks.provider.dart deleted file mode 100644 index 6ea103b..0000000 --- a/lib/screens/bookmarks/provider/bookmarks.provider.dart +++ /dev/null @@ -1,243 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/webview/ui/webview.dart'; -import 'package:linkdy/screens/bookmarks/provider/common_functions.dart'; -import 'package:linkdy/screens/bookmarks/model/bookmarks.model.dart'; -import 'package:linkdy/screens/webview/ui/invalid_bookmark.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/utils/open_url.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; -import 'package:linkdy/constants/enums.dart'; - -part 'bookmarks.provider.g.dart'; - -@riverpod -FutureOr bookmarksRequest( - BookmarksRequestRef ref, - ReadStatus readStatus, - SortingType type, - SortingWay way, - int limit, -) async { - final result = await ref.watch(apiClientProvider)!.fetchBookmarks( - limit: limit, - offset: 0, - unread: readStatus, - sort: "${type == SortingType.title ? "title" : "added"}_${way == SortingWay.ascendant ? "asc" : "desc"}", - ); - - if (result.successful == true && result.content?.results != null && result.content?.count != null) { - ref.read(bookmarksProvider).bookmarks = result.content!.results!; - ref.read(bookmarksProvider).maxNumber = result.content!.count!; - ref.read(bookmarksProvider).currentPage = 0; - ref.read(bookmarksProvider).loadingMore = false; - ref.read(bookmarksProvider).inialLoadStatus = LoadStatus.loaded; - } else { - ref.read(bookmarksProvider).inialLoadStatus = LoadStatus.error; - } - ref.read(bookmarksProvider.notifier).notifyListeners(); -} - -@riverpod -FutureOr bookmarksRequestLoadMore(BookmarksRequestLoadMoreRef ref) async { - final provider = ref.watch(bookmarksProvider); - - final sortingType = ref.watch(bookmarksProvider).sortingType; - final sortingWay = ref.watch(bookmarksProvider).sortingWay; - - final newOffset = provider.limit * (provider.currentPage + 1); - - final result = await ref.watch(apiClientProvider)!.fetchBookmarks( - limit: provider.limit, - offset: newOffset, - unread: ref.read(bookmarksProvider).readStatus, - sort: - "${sortingType == SortingType.title ? "title" : "added"}_${sortingWay == SortingWay.ascendant ? "asc" : "desc"}", - ); - - if (result.successful == true) { - // ref.read(faviconStoreProvider.notifier).loadFavicons(result.content!.results!); - provider.bookmarks = [...provider.bookmarks, ...result.content!.results!]; - provider.maxNumber = result.content!.count!; - provider.currentPage = provider.currentPage + 1; - } - - ref.read(bookmarksProvider.notifier).setLoadingMore(false); -} - -const _webViewRoute = "wb"; -const _webViewRoutePath = "/wb"; - -@riverpod -class Bookmarks extends _$Bookmarks { - @override - BookmarksModel build() { - final model = BookmarksModel( - bookmarks: [], - webViewRouter: GoRouter( - routes: [ - GoRoute( - path: "/", - builder: (context, state) => const SizedBox(), - routes: [ - GoRoute( - path: _webViewRoute, - pageBuilder: (context, state) { - final extra = state.extra; - if (extra is Bookmark) { - return CustomTransitionPage( - child: WebViewScreen(bookmark: extra), - transitionsBuilder: (context, animation, secondaryAnimation, child) => child, - ); - } else { - return CustomTransitionPage( - child: const InvalidBookmarkScreen(), - transitionsBuilder: (context, animation, secondaryAnimation, child) => child, - ); - } - }, - ), - ], - ), - ], - ), - ); - ref.read(bookmarksRequestProvider(model.readStatus, model.sortingType, model.sortingWay, model.limit)); - return model; - } - - void setCurrentPage(int page) { - state.currentPage = page; - } - - void setLimit(int limit) { - state.limit = limit; - } - - void setLoadingMore(bool value) { - state.loadingMore = value; - ref.notifyListeners(); - } - - void notifyListeners() { - ref.notifyListeners(); - } - - void setBookmarks(List bookmarks) { - state.bookmarks = bookmarks; - ref.notifyListeners(); - } - - void setReadStatus(ReadStatus status) { - state.readStatus = status; - ref.read(bookmarksRequestProvider(status, state.sortingType, state.sortingWay, state.limit)); - ref.notifyListeners(); - } - - void setSortingType(SortingType type) { - state.sortingType = type; - ref.read(bookmarksRequestProvider(state.readStatus, type, state.sortingWay, state.limit)); - ref.notifyListeners(); - } - - void setSortingWay(SortingWay way) { - state.sortingWay = way; - ref.read(bookmarksRequestProvider(state.readStatus, state.sortingType, way, state.limit)); - ref.notifyListeners(); - } - - void pushRoute(String path, bool splitMode) { - if (splitMode == true && state.webViewRouter.canPop()) { - state.selectedBookmark = null; - ref.notifyListeners(); - state.webViewRouter.pop(); - } - ref.read(routerProvider).push(path); - } - - void clearSelectedBookmark() { - state.selectedBookmark = null; - ref.notifyListeners(); - } - - void selectBookmark(Bookmark bookmark, double width) { - if (ref.watch(appStatusProvider).openLinksBrowser == OpenLinksBrowser.browserCustomTab) { - openUrlCustomTab(bookmark.url!); - } else if (ref.watch(appStatusProvider).openLinksBrowser == OpenLinksBrowser.systemBrowser) { - openUrlSystemBrowser(bookmark.url!); - } else { - if (width <= Sizes.tabletBreakpoint) { - ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark); - } else if (bookmark != state.selectedBookmark) { - state.webViewRouter.go(_webViewRoutePath, extra: bookmark); - } - state.selectedBookmark = bookmark; - ref.notifyListeners(); - } - } - - Future refresh() async { - await ref.read(bookmarksRequestProvider(state.readStatus, state.sortingType, state.sortingWay, state.limit).future); - } - - void deleteBookmark(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.deleteBookmark( - scaffoldMessengerKey: ScaffoldMessengerKeys.bookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result == true) { - state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); - ref.notifyListeners(); - } - } - - void markAsReadUnread(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.markAsReadUnread( - scaffoldMessengerKey: ScaffoldMessengerKeys.bookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result != null) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); - ref.notifyListeners(); - } - } - - void archiveUnarchive(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.archiveUnarchive( - scaffoldMessengerKey: ScaffoldMessengerKeys.bookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result == true) { - // On this case the bookmark always will pass from unarchived to archived - state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); - ref.notifyListeners(); - } - } - - void shareUnshare(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.shareUnshare( - scaffoldMessengerKey: ScaffoldMessengerKeys.bookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result != null) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); - ref.notifyListeners(); - } - } -} diff --git a/lib/screens/bookmarks/provider/bookmarks.provider.g.dart b/lib/screens/bookmarks/provider/bookmarks.provider.g.dart deleted file mode 100644 index 371357b..0000000 --- a/lib/screens/bookmarks/provider/bookmarks.provider.g.dart +++ /dev/null @@ -1,240 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'bookmarks.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$bookmarksRequestHash() => r'b1ac82693d1acf93e0c5c51bbfe8674e1cf3f487'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -/// See also [bookmarksRequest]. -@ProviderFor(bookmarksRequest) -const bookmarksRequestProvider = BookmarksRequestFamily(); - -/// See also [bookmarksRequest]. -class BookmarksRequestFamily extends Family> { - /// See also [bookmarksRequest]. - const BookmarksRequestFamily(); - - /// See also [bookmarksRequest]. - BookmarksRequestProvider call( - ReadStatus readStatus, - SortingType type, - SortingWay way, - int limit, - ) { - return BookmarksRequestProvider( - readStatus, - type, - way, - limit, - ); - } - - @override - BookmarksRequestProvider getProviderOverride( - covariant BookmarksRequestProvider provider, - ) { - return call( - provider.readStatus, - provider.type, - provider.way, - provider.limit, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'bookmarksRequestProvider'; -} - -/// See also [bookmarksRequest]. -class BookmarksRequestProvider extends AutoDisposeFutureProvider { - /// See also [bookmarksRequest]. - BookmarksRequestProvider( - ReadStatus readStatus, - SortingType type, - SortingWay way, - int limit, - ) : this._internal( - (ref) => bookmarksRequest( - ref as BookmarksRequestRef, - readStatus, - type, - way, - limit, - ), - from: bookmarksRequestProvider, - name: r'bookmarksRequestProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$bookmarksRequestHash, - dependencies: BookmarksRequestFamily._dependencies, - allTransitiveDependencies: - BookmarksRequestFamily._allTransitiveDependencies, - readStatus: readStatus, - type: type, - way: way, - limit: limit, - ); - - BookmarksRequestProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.readStatus, - required this.type, - required this.way, - required this.limit, - }) : super.internal(); - - final ReadStatus readStatus; - final SortingType type; - final SortingWay way; - final int limit; - - @override - Override overrideWith( - FutureOr Function(BookmarksRequestRef provider) create, - ) { - return ProviderOverride( - origin: this, - override: BookmarksRequestProvider._internal( - (ref) => create(ref as BookmarksRequestRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - readStatus: readStatus, - type: type, - way: way, - limit: limit, - ), - ); - } - - @override - AutoDisposeFutureProviderElement createElement() { - return _BookmarksRequestProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is BookmarksRequestProvider && - other.readStatus == readStatus && - other.type == type && - other.way == way && - other.limit == limit; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, readStatus.hashCode); - hash = _SystemHash.combine(hash, type.hashCode); - hash = _SystemHash.combine(hash, way.hashCode); - hash = _SystemHash.combine(hash, limit.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin BookmarksRequestRef on AutoDisposeFutureProviderRef { - /// The parameter `readStatus` of this provider. - ReadStatus get readStatus; - - /// The parameter `type` of this provider. - SortingType get type; - - /// The parameter `way` of this provider. - SortingWay get way; - - /// The parameter `limit` of this provider. - int get limit; -} - -class _BookmarksRequestProviderElement - extends AutoDisposeFutureProviderElement with BookmarksRequestRef { - _BookmarksRequestProviderElement(super.provider); - - @override - ReadStatus get readStatus => (origin as BookmarksRequestProvider).readStatus; - @override - SortingType get type => (origin as BookmarksRequestProvider).type; - @override - SortingWay get way => (origin as BookmarksRequestProvider).way; - @override - int get limit => (origin as BookmarksRequestProvider).limit; -} - -String _$bookmarksRequestLoadMoreHash() => - r'3c1a68da25d2dc9d3b6520d3073186520dfe5e5d'; - -/// See also [bookmarksRequestLoadMore]. -@ProviderFor(bookmarksRequestLoadMore) -final bookmarksRequestLoadMoreProvider = - AutoDisposeFutureProvider.internal( - bookmarksRequestLoadMore, - name: r'bookmarksRequestLoadMoreProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$bookmarksRequestLoadMoreHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef BookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef; -String _$bookmarksHash() => r'21cfb29298db2edcea8ce2b162e2f312972e9f3b'; - -/// See also [Bookmarks]. -@ProviderFor(Bookmarks) -final bookmarksProvider = - AutoDisposeNotifierProvider.internal( - Bookmarks.new, - name: r'bookmarksProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$bookmarksHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$Bookmarks = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/bookmarks/provider/common_functions.dart b/lib/screens/bookmarks/provider/common_functions.dart deleted file mode 100644 index 5e24be0..0000000 --- a/lib/screens/bookmarks/provider/common_functions.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/models/data/patch_bookmark_data.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/utils/snackbar.dart'; -import 'package:linkdy/models/data/set_bookmark_data.dart'; -import 'package:linkdy/services/api_client.dart'; -import 'package:linkdy/utils/process_modal.dart'; - -class BookmarkCommonFunctions { - static Future deleteBookmark({ - required AutoDisposeNotifierProviderRef ref, - required Bookmark bookmark, - required ApiClientService apiClient, - required GlobalKey scaffoldMessengerKey, - }) async { - final processModal = ProcessModal(); - processModal.open(t.bookmarks.bookmarkOptions.deletingBookmark); - - final result = await apiClient.postDeleteBookmark(bookmark.id!); - - processModal.close(); - if (result.successful == true) { - showSnackbar( - key: scaffoldMessengerKey, - label: t.bookmarks.bookmarkOptions.bookmarkDeleted, - color: Colors.green, - ); - } else { - showSnackbar( - key: scaffoldMessengerKey, - label: t.bookmarks.bookmarkOptions.bookmarkNotDeleted, - color: Colors.red, - ); - } - return result.successful; - } - - static Future markAsReadUnread({ - required AutoDisposeNotifierProviderRef ref, - required Bookmark bookmark, - required ApiClientService apiClient, - required GlobalKey scaffoldMessengerKey, - }) async { - final processModal = ProcessModal(); - processModal.open( - bookmark.unread == true ? t.bookmarks.bookmarkOptions.markingAsRead : t.bookmarks.bookmarkOptions.markingAsUnead, - ); - - final result = await apiClient.putUpdateBookmark( - bookmark.id!, - SetBookmarkData( - url: bookmark.url!, - description: bookmark.description ?? '', - isArchived: bookmark.isArchived ?? false, - shared: bookmark.shared ?? false, - unread: bookmark.unread == true ? false : true, - tagNames: bookmark.tagNames?.join(",") ?? '', - title: bookmark.title ?? '', - notes: bookmark.notes ?? '', - ), - ); - - processModal.close(); - if (result.successful == true) { - showSnackbar( - key: scaffoldMessengerKey, - label: bookmark.unread == true - ? t.bookmarks.bookmarkOptions.markedAsReadSuccessfully - : t.bookmarks.bookmarkOptions.markedAsUnreadSuccessfully, - color: Colors.green, - ); - return result.content; - } else { - showSnackbar( - key: scaffoldMessengerKey, - label: bookmark.unread == true - ? t.bookmarks.bookmarkOptions.bookmarkNotMarkedAsRead - : t.bookmarks.bookmarkOptions.bookmarkNotMarkedAsUnread, - color: Colors.red, - ); - return null; - } - } - - static Future archiveUnarchive({ - required AutoDisposeNotifierProviderRef ref, - required Bookmark bookmark, - required ApiClientService apiClient, - required GlobalKey scaffoldMessengerKey, - }) async { - final processModal = ProcessModal(); - processModal.open( - bookmark.isArchived == true - ? t.bookmarks.bookmarkOptions.unarchivingBookmark - : t.bookmarks.bookmarkOptions.archivingBookmark, - ); - - final result = bookmark.isArchived == true - ? await apiClient.postUnrchiveBookmark(bookmark.id!) - : await apiClient.postArchiveBookmark(bookmark.id!); - - processModal.close(); - if (result.successful == true) { - showSnackbar( - key: scaffoldMessengerKey, - label: bookmark.isArchived == true - ? t.bookmarks.bookmarkOptions.bookmarkUnrchivedSuccessfully - : t.bookmarks.bookmarkOptions.bookmarkArchivedSuccessfully, - color: Colors.green, - ); - } else { - showSnackbar( - key: scaffoldMessengerKey, - label: bookmark.isArchived == true - ? t.bookmarks.bookmarkOptions.bookmarkNotUnrchived - : t.bookmarks.bookmarkOptions.bookmarkNotArchived, - color: Colors.red, - ); - } - return result.successful; - } - - static Future shareUnshare({ - required AutoDisposeNotifierProviderRef ref, - required Bookmark bookmark, - required ApiClientService apiClient, - required GlobalKey scaffoldMessengerKey, - }) async { - final processModal = ProcessModal(); - processModal.open( - bookmark.shared == true ? t.bookmarks.shareOptions.unsharingBookmark : t.bookmarks.shareOptions.sharingBookmark, - ); - - final result = await apiClient.patchUpdateBookmark( - bookmark.id!, - PatchBookmarkData( - shared: !bookmark.shared!, - ), - ); - - processModal.close(); - if (result.successful == true) { - showSnackbar( - key: scaffoldMessengerKey, - label: bookmark.shared == true - ? t.bookmarks.shareOptions.bookmarkUnsharedSuccessfully - : t.bookmarks.shareOptions.bookmarkSharedSuccessfully, - color: Colors.green, - ); - return result.content; - } else { - showSnackbar( - key: scaffoldMessengerKey, - label: bookmark.shared == true - ? t.bookmarks.shareOptions.bookmarkNotUnshared - : t.bookmarks.shareOptions.bookmarkNotShared, - color: Colors.red, - ); - return null; - } - } -} diff --git a/lib/screens/bookmarks/provider/search_bookmarks.provider.dart b/lib/screens/bookmarks/provider/search_bookmarks.provider.dart deleted file mode 100644 index 770c141..0000000 --- a/lib/screens/bookmarks/provider/search_bookmarks.provider.dart +++ /dev/null @@ -1,222 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/webview/ui/webview.dart'; -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/screens/bookmarks/provider/common_functions.dart'; -import 'package:linkdy/screens/bookmarks/model/search_bookmarks.model.dart'; -import 'package:linkdy/screens/webview/ui/invalid_bookmark.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/utils/open_url.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -part 'search_bookmarks.provider.g.dart'; - -@riverpod -FutureOr fetchSearchBookmarks(FetchSearchBookmarksRef ref, int limit) async { - if (ref.watch(searchBookmarksProvider).searchTerm == "") return null; - - final result = await ref.read(apiClientProvider)!.fetchBookmarks( - q: ref.watch(searchBookmarksProvider).searchTerm, - limit: limit, - offset: 0, - ); - - if (result.successful == true) { - ref.read(searchBookmarksProvider).bookmarks = result.content!.results!; - ref.read(searchBookmarksProvider).maxNumber = result.content!.count!; - ref.read(searchBookmarksProvider).currentPage = 0; - ref.read(searchBookmarksProvider).loadingMore = false; - ref.read(searchBookmarksProvider).inialLoadStatus = LoadStatus.loaded; - } else { - ref.read(searchBookmarksProvider).inialLoadStatus = LoadStatus.error; - } - ref.read(searchBookmarksProvider.notifier).notifyListeners(); -} - -@riverpod -FutureOr fetchSearchBookmarksLoadMore(FetchSearchBookmarksLoadMoreRef ref) async { - final provider = ref.watch(searchBookmarksProvider); - - final newOffset = provider.limit * (provider.currentPage + 1); - - final result = await ref.watch(apiClientProvider)!.fetchBookmarks( - q: provider.searchTerm, - limit: provider.limit, - offset: newOffset, - ); - - if (result.successful == true) { - provider.bookmarks = [...provider.bookmarks, ...result.content!.results!]; - provider.maxNumber = result.content!.count!; - provider.currentPage = provider.currentPage + 1; - } - - ref.read(searchBookmarksProvider.notifier).setLoadingMore(false); -} - -const _webViewRoute = "wb"; -const _webViewRoutePath = "/wb"; - -@riverpod -class SearchBookmarks extends _$SearchBookmarks { - @override - SearchBookmarksModel build() { - final model = SearchBookmarksModel( - searchController: TextEditingController(), - bookmarks: [], - webViewRouter: GoRouter( - routes: [ - GoRoute( - path: "/", - builder: (context, state) => const SizedBox(), - routes: [ - GoRoute( - path: _webViewRoute, - pageBuilder: (context, state) { - final extra = state.extra; - if (extra is Bookmark) { - return CustomTransitionPage( - child: WebViewScreen(bookmark: extra), - transitionsBuilder: (context, animation, secondaryAnimation, child) => child, - ); - } else { - return CustomTransitionPage( - child: const InvalidBookmarkScreen(), - transitionsBuilder: (context, animation, secondaryAnimation, child) => child, - ); - } - }, - ), - ], - ), - ], - ), - ); - ref.read(fetchSearchBookmarksProvider(model.limit)); - return model; - } - - void clearSearch() { - state.searchController.clear(); - state.searchTerm = ""; - ref.notifyListeners(); - } - - void notifyOnChange() { - ref.notifyListeners(); - } - - void setSearchTerm() { - state.searchTerm = state.searchController.text; - ref.notifyListeners(); - } - - void setLoadingMore(bool value) { - state.loadingMore = value; - ref.notifyListeners(); - } - - void setInitialLoadStatus(LoadStatus status) { - state.inialLoadStatus = status; - ref.notifyListeners(); - } - - void notifyListeners() { - ref.notifyListeners(); - } - - void clearSelectedBookmark() { - state.selectedBookmark = null; - ref.notifyListeners(); - } - - void selectBookmark(Bookmark bookmark, double width) { - if (ref.watch(appStatusProvider).openLinksBrowser == OpenLinksBrowser.browserCustomTab) { - openUrlCustomTab(bookmark.url!); - } else if (ref.watch(appStatusProvider).openLinksBrowser == OpenLinksBrowser.systemBrowser) { - openUrlSystemBrowser(bookmark.url!); - } else { - if (width <= Sizes.tabletBreakpoint) { - ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark); - } else if (bookmark != state.selectedBookmark) { - state.webViewRouter.go(_webViewRoutePath, extra: bookmark); - } - state.selectedBookmark = bookmark; - ref.notifyListeners(); - } - } - - void deleteBookmark(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.deleteBookmark( - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - scaffoldMessengerKey: ScaffoldMessengerKeys.search, - ); - if (result == true) { - state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); - ref.notifyListeners(); - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.where((b) => b.id != bookmark.id).toList()); - } - } - - void markAsReadUnread(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.markAsReadUnread( - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - scaffoldMessengerKey: ScaffoldMessengerKeys.search, - ); - if (result != null) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); - ref.notifyListeners(); - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.map((b) => b.id == result.id ? result : b).toList()); - } - } - - void archiveUnarchive(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.archiveUnarchive( - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - scaffoldMessengerKey: ScaffoldMessengerKeys.search, - ); - if (result == true) { - // On this case the bookmark always will pass from unarchived to archived - state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); - ref.notifyListeners(); - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.where((b) => b.id != bookmark.id).toList()); - } - } - - void shareUnshare(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.shareUnshare( - scaffoldMessengerKey: ScaffoldMessengerKeys.search, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result != null) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); - ref.notifyListeners(); - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.map((b) => b.id == result.id ? result : b).toList()); - } - } -} diff --git a/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart b/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart deleted file mode 100644 index 57c9aad..0000000 --- a/lib/screens/bookmarks/provider/search_bookmarks.provider.g.dart +++ /dev/null @@ -1,194 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'search_bookmarks.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$fetchSearchBookmarksHash() => - r'a854d28b2c2b6761cfd716bcbe081b54fbbf29ef'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -/// See also [fetchSearchBookmarks]. -@ProviderFor(fetchSearchBookmarks) -const fetchSearchBookmarksProvider = FetchSearchBookmarksFamily(); - -/// See also [fetchSearchBookmarks]. -class FetchSearchBookmarksFamily extends Family> { - /// See also [fetchSearchBookmarks]. - const FetchSearchBookmarksFamily(); - - /// See also [fetchSearchBookmarks]. - FetchSearchBookmarksProvider call( - int limit, - ) { - return FetchSearchBookmarksProvider( - limit, - ); - } - - @override - FetchSearchBookmarksProvider getProviderOverride( - covariant FetchSearchBookmarksProvider provider, - ) { - return call( - provider.limit, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'fetchSearchBookmarksProvider'; -} - -/// See also [fetchSearchBookmarks]. -class FetchSearchBookmarksProvider extends AutoDisposeFutureProvider { - /// See also [fetchSearchBookmarks]. - FetchSearchBookmarksProvider( - int limit, - ) : this._internal( - (ref) => fetchSearchBookmarks( - ref as FetchSearchBookmarksRef, - limit, - ), - from: fetchSearchBookmarksProvider, - name: r'fetchSearchBookmarksProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$fetchSearchBookmarksHash, - dependencies: FetchSearchBookmarksFamily._dependencies, - allTransitiveDependencies: - FetchSearchBookmarksFamily._allTransitiveDependencies, - limit: limit, - ); - - FetchSearchBookmarksProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.limit, - }) : super.internal(); - - final int limit; - - @override - Override overrideWith( - FutureOr Function(FetchSearchBookmarksRef provider) create, - ) { - return ProviderOverride( - origin: this, - override: FetchSearchBookmarksProvider._internal( - (ref) => create(ref as FetchSearchBookmarksRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - limit: limit, - ), - ); - } - - @override - AutoDisposeFutureProviderElement createElement() { - return _FetchSearchBookmarksProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is FetchSearchBookmarksProvider && other.limit == limit; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, limit.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin FetchSearchBookmarksRef on AutoDisposeFutureProviderRef { - /// The parameter `limit` of this provider. - int get limit; -} - -class _FetchSearchBookmarksProviderElement - extends AutoDisposeFutureProviderElement - with FetchSearchBookmarksRef { - _FetchSearchBookmarksProviderElement(super.provider); - - @override - int get limit => (origin as FetchSearchBookmarksProvider).limit; -} - -String _$fetchSearchBookmarksLoadMoreHash() => - r'f07a6a89f5a87a0f26d3a8d2d49f1d98ce36a287'; - -/// See also [fetchSearchBookmarksLoadMore]. -@ProviderFor(fetchSearchBookmarksLoadMore) -final fetchSearchBookmarksLoadMoreProvider = - AutoDisposeFutureProvider.internal( - fetchSearchBookmarksLoadMore, - name: r'fetchSearchBookmarksLoadMoreProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$fetchSearchBookmarksLoadMoreHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef FetchSearchBookmarksLoadMoreRef = AutoDisposeFutureProviderRef; -String _$searchBookmarksHash() => r'545924de28fd2ce74b8c243db8dda33c5fd079a2'; - -/// See also [SearchBookmarks]. -@ProviderFor(SearchBookmarks) -final searchBookmarksProvider = - AutoDisposeNotifierProvider.internal( - SearchBookmarks.new, - name: r'searchBookmarksProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$searchBookmarksHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$SearchBookmarks = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/bookmarks/ui/bookmark_form_modal.dart b/lib/screens/bookmarks/ui/bookmark_form_modal.dart deleted file mode 100644 index 7e0f15a..0000000 --- a/lib/screens/bookmarks/ui/bookmark_form_modal.dart +++ /dev/null @@ -1,475 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:easy_autocomplete/easy_autocomplete.dart'; - -import 'package:linkdy/screens/bookmarks/provider/bookmark_form.provider.dart'; -import 'package:linkdy/widgets/section_label.dart'; - -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/constants/enums.dart'; - -class BookmarkFormModal extends ConsumerStatefulWidget { - final Bookmark? bookmark; - final String? url; - - const BookmarkFormModal({ - super.key, - this.bookmark, - this.url, - }); - - @override - BookmarkFormModalState createState() => BookmarkFormModalState(); -} - -class BookmarkFormModalState extends ConsumerState { - @override - void initState() { - if (widget.bookmark == null) { - ref.read(bookmarkFormProvider).tags = ref.read(appStatusProvider).defaultTags; - } - if (widget.bookmark != null) { - ref.read(bookmarkFormProvider.notifier).initializeProvider(widget.bookmark!); - } - if (widget.url != null) { - ref.read(bookmarkFormProvider.notifier).initializeProviderUrl(widget.url!); - } - super.initState(); - } - - @override - Widget build(BuildContext context) { - final width = MediaQuery.of(context).size.width; - - if (width > Sizes.tabletBreakpoint) { - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.addBookmark, - child: Dialog( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 500, maxHeight: 700), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - CloseButton( - onPressed: () => Navigator.pop(context), - ), - const SizedBox(width: 16), - Text( - widget.bookmark != null - ? t.bookmarks.addBookmark.editBookmark - : t.bookmarks.addBookmark.addBookmark, - style: const TextStyle(fontSize: 24), - ), - ], - ), - IconButton( - onPressed: ref.watch(bookmarkFormProvider).bookmarkValid == true - ? () => ref.read(bookmarkFormProvider.notifier).saveBookmark() - : null, - icon: const Icon(Icons.save_rounded), - tooltip: t.generic.save, - ), - ], - ), - ), - Expanded( - child: ListView( - children: const [_ModalContent()], - ), - ), - ], - ), - ), - ), - ); - } else { - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.addBookmark, - child: Dialog.fullscreen( - child: Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - leading: CloseButton( - onPressed: () => Navigator.pop(context), - ), - title: Text( - widget.bookmark != null - ? t.bookmarks.addBookmark.editBookmark - : t.bookmarks.addBookmark.addBookmark, - ), - actions: [ - IconButton( - onPressed: ref.watch(bookmarkFormProvider).bookmarkValid == true - ? () => ref.read(bookmarkFormProvider.notifier).saveBookmark() - : null, - icon: const Icon(Icons.save_rounded), - tooltip: t.generic.save, - ), - const SizedBox(width: 8), - ], - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: const [ - _ModalContent(), - SizedBox(height: 16), - ], - ), - ], - ), - ), - ), - ), - ), - ), - ); - } - } -} - -class _ModalContent extends ConsumerWidget { - const _ModalContent(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final provider = ref.watch(bookmarkFormProvider); - - final tags = ref.watch(getTagsProvider); - - final enabledFields = provider.bookmarkValid == true; - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 16), - SectionLabel( - label: t.bookmarks.addBookmark.bookmarkUrl, - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 0, - ), - ), - const SizedBox(height: 24), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: provider.urlController, - onChanged: ref.read(bookmarkFormProvider.notifier).validateUrl, - enabled: provider.checkBookmarkLoadStatus != LoadStatus.loading, - autocorrect: false, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - errorText: provider.urlError, - labelText: t.bookmarks.addBookmark.url, - ), - ), - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Center( - child: ElevatedButton( - onPressed: provider.checkBookmarkLoadStatus == null && - provider.urlError == null && - provider.urlController.text != "" - ? () => ref.read(bookmarkFormProvider.notifier).checkUrlDetails(updateState: true) - : null, - style: ButtonStyle( - foregroundColor: provider.checkBookmarkLoadStatus == LoadStatus.loaded - ? const WidgetStatePropertyAll(Colors.green) - : provider.checkBookmarkLoadStatus == LoadStatus.error - ? const WidgetStatePropertyAll(Colors.red) - : null, - backgroundColor: provider.checkBookmarkLoadStatus == LoadStatus.loaded - ? WidgetStatePropertyAll(Colors.green.withOpacity(0.15)) - : provider.checkBookmarkLoadStatus == LoadStatus.error - ? WidgetStatePropertyAll(Colors.red.withOpacity(0.15)) - : null, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (provider.checkBookmarkLoadStatus == null) Text(t.bookmarks.addBookmark.validateUrl), - if (provider.checkBookmarkLoadStatus == LoadStatus.loading) ...[ - const SizedBox( - width: 12, - height: 12, - child: CircularProgressIndicator( - strokeWidth: 2, - ), - ), - const SizedBox(width: 8), - Text(t.bookmarks.addBookmark.checkingUrl), - ], - if (provider.checkBookmarkLoadStatus == LoadStatus.loaded) ...[ - const Icon(Icons.check_circle_rounded), - const SizedBox(width: 8), - Text(t.bookmarks.addBookmark.urlValid), - ], - if (provider.checkBookmarkLoadStatus == LoadStatus.error) ...[ - const Icon(Icons.error_rounded), - const SizedBox(width: 8), - Text(t.bookmarks.addBookmark.cannotCheckUrl), - ], - ], - ), - ), - ), - ), - if (provider.bookmarkExists == true) - Card( - margin: const EdgeInsets.all(16), - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - const Icon(Icons.info_rounded), - const SizedBox(width: 16), - Flexible(child: Text(t.bookmarks.addBookmark.urlAlreadyBookmarked)), - ], - ), - ), - ), - SectionLabel( - label: t.bookmarks.addBookmark.bookmarkDetails, - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 24, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: provider.titleController, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.title_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - labelText: t.bookmarks.addBookmark.title, - floatingLabelBehavior: - provider.bookmarkValid == true ? FloatingLabelBehavior.always : FloatingLabelBehavior.auto, - helperText: t.bookmarks.addBookmark.leaveEmptyUseWebsiteTitle, - enabled: enabledFields, - ), - ), - ), - const SizedBox(height: 24), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TextFormField( - controller: provider.descriptionController, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.description_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - labelText: t.bookmarks.addBookmark.description, - floatingLabelBehavior: - provider.bookmarkValid == true ? FloatingLabelBehavior.always : FloatingLabelBehavior.auto, - helperText: t.bookmarks.addBookmark.leaveEmptyUseWebsiteDescription, - enabled: enabledFields, - ), - ), - ), - SectionLabel( - label: t.bookmarks.addBookmark.tags, - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 24, - ), - ), - if (tags.isLoading == false) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - children: [ - if (enabledFields == true) - Row( - children: [ - Expanded( - child: EasyAutocomplete( - controller: provider.tagsController, - onChanged: ref.read(bookmarkFormProvider.notifier).validateTagInput, - suggestions: (tags.value?.content?.results?.map((t) => t.name!).toList() ?? [])..sort(), - textCapitalization: TextCapitalization.none, - decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - labelText: t.bookmarks.addBookmark.tags, - errorText: provider.tagsError, - ), - suggestionBuilder: (data) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Text( - data, - style: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - ), - onSubmitted: provider.tagsController.text != "" && provider.tagsError == null - ? (v) { - ref.read(bookmarkFormProvider.notifier).setTags([...provider.tags, v]); - ref.read(bookmarkFormProvider.notifier).clearTagsController(); - } - : null, - ), - ), - const SizedBox(width: 16), - IconButton( - onPressed: provider.tagsController.text != "" && provider.tagsError == null - ? () { - ref - .read(bookmarkFormProvider.notifier) - .setTags([...provider.tags, provider.tagsController.text]); - ref.read(bookmarkFormProvider.notifier).clearTagsController(); - } - : null, - icon: const Icon(Icons.check_rounded), - tooltip: t.bookmarks.addBookmark.addTag, - ), - ], - ), - if (enabledFields == true) const SizedBox(height: 16), - SizedBox( - height: 40, - child: provider.tags.isNotEmpty - ? ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: provider.tags.length, - separatorBuilder: (context, index) => const SizedBox(width: 8), - itemBuilder: (context, index) => InputChip( - label: Text(provider.tags[index]), - isEnabled: enabledFields, - onDeleted: () => ref - .read(bookmarkFormProvider.notifier) - .setTags(provider.tags.where((tag) => tag != provider.tags[index]).toList()), - ), - ) - : Center( - child: Text( - t.bookmarks.addBookmark.noTagsAdded, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.secondary, - ), - ), - ), - ), - ], - ), - ), - SectionLabel( - label: t.bookmarks.addBookmark.others, - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 24, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: SizedBox( - height: 150, - child: TextFormField( - controller: provider.notesController, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.note_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - labelText: t.bookmarks.addBookmark.notes, - helperText: t.generic.optional, - ), - autocorrect: false, - expands: true, - minLines: null, - maxLines: null, - textAlignVertical: TextAlignVertical.top, - enabled: enabledFields, - ), - ), - ), - const SizedBox(height: 12), - SwitchListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - title: Text(t.bookmarks.addBookmark.markAsUnread), - subtitle: Text(t.bookmarks.addBookmark.markAsUnreadDescription), - value: provider.markAsUnread, - onChanged: provider.bookmarkValid == true - ? (v) => ref.read(bookmarkFormProvider.notifier).updateMarkAsUnread(v) - : null, - ), - SwitchListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - title: Text(t.bookmarks.addBookmark.share), - subtitle: Text(t.bookmarks.addBookmark.shareDescription), - value: provider.share, - onChanged: - provider.bookmarkValid == true ? (v) => ref.read(bookmarkFormProvider.notifier).updateShare(v) : null, - ), - const SizedBox(height: 16), - ], - ); - } -} - -void openBookmarkFormModal({ - required BuildContext context, - required double width, - String? url, - Bookmark? bookmark, -}) { - showGeneralDialog( - context: context, - barrierColor: Colors.black54, - transitionBuilder: (context, anim1, anim2, child) { - return SlideTransition( - position: Tween(begin: const Offset(0, 1), end: const Offset(0, 0)).animate( - CurvedAnimation(parent: anim1, curve: Curves.easeInOutCubicEmphasized), - ), - child: child, - ); - }, - pageBuilder: (context, animation, secondaryAnimation) => BookmarkFormModal(bookmark: bookmark, url: url), - ); -} diff --git a/lib/screens/bookmarks/ui/bookmarks.dart b/lib/screens/bookmarks/ui/bookmarks.dart deleted file mode 100644 index 09c8b49..0000000 --- a/lib/screens/bookmarks/ui/bookmarks.dart +++ /dev/null @@ -1,300 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -import 'package:linkdy/screens/bookmarks/ui/visualization_modal.dart'; -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/widgets/bookmark_item/bookmark_item.dart'; -import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart'; -import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; -import 'package:linkdy/screens/bookmarks/ui/search_bookmarks.dart'; -import 'package:linkdy/widgets/error_screen.dart'; -import 'package:linkdy/widgets/no_data_screen.dart'; - -import 'package:linkdy/providers/receive_sharing_intent_url.provider.dart'; -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/widgets/system_overlay_style.dart'; - -final GlobalKey _searchButtonKey = GlobalKey(); -final webviewBookmarksKey = GlobalKey(); - -class BookmarksScreen extends HookConsumerWidget { - const BookmarksScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final width = MediaQuery.of(context).size.width; - final sharedUrl = ref.watch(receiveSharingIntentUrlProvider); - - WidgetsBinding.instance.addPostFrameCallback((_) { - if (sharedUrl == null) return; - openBookmarkFormModal(context: context, width: width, url: sharedUrl); - ref.read(receiveSharingIntentUrlProvider.notifier).setValue(null); - }); - - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.bookmarks, - child: LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth > Sizes.tabletBreakpoint) { - return Row( - children: [ - const Expanded(flex: 2, child: _List(tabletMode: true)), - Expanded( - flex: 3, - child: Material( - child: Router.withConfig(config: ref.watch(bookmarksProvider).webViewRouter), - ), - ), - ], - ); - } else { - return const _List(tabletMode: false); - } - }, - ), - ); - } -} - -class _List extends ConsumerWidget { - final bool tabletMode; - - const _List({ - required this.tabletMode, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final bookmarks = ref.watch(bookmarksProvider); - - final width = MediaQuery.of(context).size.width; - - void openSearchModal() { - if (_searchButtonKey.currentContext == null) return; - if (tabletMode == true && ref.read(bookmarksProvider).webViewRouter.canPop()) { - ref.read(bookmarksProvider.notifier).clearSelectedBookmark(); - ref.read(bookmarksProvider).webViewRouter.pop(); - } - // RenderBox box = _searchButtonKey.currentContext!.findRenderObject() as RenderBox; - // Offset position = box.localToGlobal(Offset.zero); - Navigator.of(context, rootNavigator: true).push( - MaterialPageRoute( - builder: (ctx) => const SearchBookmarksModal(fullscreen: true), - ), - ); - } - - bool scrollListener(ScrollUpdateNotification scrollNotification) { - if (scrollNotification.metrics.extentAfter < 100 && - bookmarks.loadingMore == false && - bookmarks.bookmarks.length < bookmarks.maxNumber) { - ref.read(bookmarksProvider.notifier).setLoadingMore(true); - ref.watch(bookmarksRequestLoadMoreProvider); - } - return false; - } - - return OverlayStyle( - child: Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text(t.bookmarks.bookmarks), - if (bookmarks.readStatus == ReadStatus.read || bookmarks.readStatus == ReadStatus.unread) - Container( - margin: const EdgeInsets.only(left: 8), - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Theme.of(context).colorScheme.primaryContainer, - ), - child: Row( - children: [ - Icon( - bookmarks.readStatus == ReadStatus.read - ? Icons.mark_email_read_rounded - : Icons.mark_as_unread_rounded, - size: 14, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - const SizedBox(width: 4), - Text( - bookmarks.readStatus == ReadStatus.read ? t.bookmarks.read : t.bookmarks.unread, - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onPrimaryContainer, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ], - ), - actions: [ - IconButton( - key: _searchButtonKey, - onPressed: openSearchModal, - icon: const Icon(Icons.search_rounded), - tooltip: t.bookmarks.search.searchBookmarks, - ), - IconButton( - onPressed: () => showModalBottomSheet( - context: context, - useRootNavigator: true, - builder: (context) => const VisualizationModal(), - isScrollControlled: true, - ), - icon: const Icon(Icons.sort_rounded), - tooltip: t.bookmarks.filterSort, - ), - PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - onTap: () => - ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.archivedBookmarks, tabletMode), - child: Row( - children: [ - const Icon(Icons.archive_rounded), - const SizedBox(width: 16), - Text(t.bookmarks.archived), - ], - ), - ), - PopupMenuItem( - onTap: () => - ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.sharedBookmarks, tabletMode), - child: Row( - children: [ - const Icon(Icons.share_rounded), - const SizedBox(width: 16), - Text(t.bookmarks.shared), - ], - ), - ), - const PopupMenuDivider(height: 1), - PopupMenuItem( - onTap: () => ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.tags, tabletMode), - child: Row( - children: [ - const Icon(Icons.label_rounded), - const SizedBox(width: 16), - Text(t.tags.tags), - ], - ), - ), - const PopupMenuDivider(height: 1), - PopupMenuItem( - onTap: () => ref.read(bookmarksProvider.notifier).pushRoute(RoutesPaths.settings, tabletMode), - child: Row( - children: [ - const Icon(Icons.settings_rounded), - const SizedBox(width: 16), - Text(t.settings.settings), - ], - ), - ), - ], - ), - const SizedBox(width: 8), - ], - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => RefreshIndicator( - displacement: 120, - onRefresh: () => ref.read(bookmarksProvider.notifier).refresh(), - child: NotificationListener( - onNotification: scrollListener, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (bookmarks.inialLoadStatus == LoadStatus.loading) - const SliverFillRemaining( - child: Center(child: CircularProgressIndicator()), - ), - if (bookmarks.inialLoadStatus == LoadStatus.error) - SliverFillRemaining( - child: ErrorScreen( - error: t.bookmarks.cannotLoadBookmarks, - ), - ), - if (bookmarks.bookmarks.isEmpty) - SliverFillRemaining( - child: NoDataScreen( - message: t.bookmarks.noBookmarksAdded, - ), - ), - if (bookmarks.bookmarks.isNotEmpty) - SliverList.builder( - itemCount: bookmarks.bookmarks.length + 1, - itemBuilder: (context, index) { - // index == bookmarks.value!.content!.results!.length -> itemCount + 1 - if (index == bookmarks.bookmarks.length) { - if (bookmarks.loadingMore) { - return const SizedBox( - height: 80, - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - // Bottom gap for FAB - return const SizedBox(height: 80); - } - return BookmarkItem( - bookmark: bookmarks.bookmarks[index], - onSelect: (b) => ref.read(bookmarksProvider.notifier).selectBookmark(b, width), - onReadUnread: ref.read(bookmarksProvider.notifier).markAsReadUnread, - onDelete: (bookmark) => showDialog( - context: context, - builder: (context) => DeleteBookmarkModal( - bookmark: bookmark, - onDelete: ref.read(bookmarksProvider.notifier).deleteBookmark, - ), - ), - onArchiveUnarchive: ref.read(bookmarksProvider.notifier).archiveUnarchive, - onShareInternally: ref.read(bookmarksProvider.notifier).shareUnshare, - onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b), - selected: bookmarks.bookmarks[index] == bookmarks.selectedBookmark, - tabletMode: tabletMode, - ); - }, - ), - ], - ), - ), - ), - ), - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: () => openBookmarkFormModal(context: context, width: width), - child: const Icon(Icons.add_rounded), - ), - ), - ); - } -} diff --git a/lib/screens/bookmarks/ui/delete_bookmark_modal.dart b/lib/screens/bookmarks/ui/delete_bookmark_modal.dart deleted file mode 100644 index 850ff97..0000000 --- a/lib/screens/bookmarks/ui/delete_bookmark_modal.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; - -class DeleteBookmarkModal extends StatelessWidget { - final Bookmark bookmark; - final void Function(Bookmark) onDelete; - - const DeleteBookmarkModal({ - super.key, - required this.bookmark, - required this.onDelete, - }); - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Column( - children: [ - Icon( - Icons.delete_rounded, - size: 24, - color: Theme.of(context).colorScheme.secondary, - ), - const SizedBox(height: 16), - Text(t.bookmarks.bookmarkOptions.deleteBookmark), - ], - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text(t.bookmarks.bookmarkOptions.followingBookmarkDeleted), - const SizedBox(height: 8), - Center( - child: Text( - bookmark.url!, - textAlign: TextAlign.center, - style: TextStyle( - fontStyle: FontStyle.italic, - color: Theme.of(context).colorScheme.secondary, - ), - ), - ), - ], - ), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(t.generic.cancel), - ), - const SizedBox(width: 8), - TextButton( - onPressed: () { - Navigator.pop(context); - onDelete(bookmark); - }, - child: Text(t.generic.confirm), - ), - ], - ), - ], - ); - } -} diff --git a/lib/screens/bookmarks/ui/search_bookmarks.dart b/lib/screens/bookmarks/ui/search_bookmarks.dart deleted file mode 100644 index e493cd0..0000000 --- a/lib/screens/bookmarks/ui/search_bookmarks.dart +++ /dev/null @@ -1,187 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/bookmarks/provider/search_bookmarks.provider.dart'; -import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart'; -import 'package:linkdy/widgets/bookmark_item/bookmark_item.dart'; -import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; -import 'package:linkdy/widgets/enter_search_term_screen.dart'; -import 'package:linkdy/widgets/no_data_screen.dart'; -import 'package:linkdy/widgets/error_screen.dart'; - -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/providers/router.provider.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class SearchBookmarksModal extends ConsumerWidget { - final bool fullscreen; - - const SearchBookmarksModal({ - super.key, - required this.fullscreen, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.search, - child: Dialog.fullscreen( - child: LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth > Sizes.tabletBreakpoint) { - return Row( - children: [ - const Expanded(flex: 2, child: _List(tabletMode: true)), - Expanded( - flex: 3, - child: Material( - child: Router.withConfig(config: ref.watch(searchBookmarksProvider).webViewRouter), - ), - ), - ], - ); - } else { - return const _List(tabletMode: false); - } - }, - ), - ), - ); - } -} - -class _List extends ConsumerWidget { - final bool tabletMode; - - const _List({ - required this.tabletMode, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final provider = ref.watch(searchBookmarksProvider); - - final width = MediaQuery.of(context).size.width; - - bool scrollListener(ScrollUpdateNotification scrollNotification) { - if (scrollNotification.metrics.extentAfter < 100 && - provider.loadingMore == false && - provider.bookmarks.length < provider.maxNumber) { - ref.read(searchBookmarksProvider.notifier).setLoadingMore(true); - ref.watch(fetchSearchBookmarksLoadMoreProvider); - } - return false; - } - - return Scaffold( - appBar: AppBar( - toolbarHeight: 68, - leading: Padding( - padding: const EdgeInsets.only(bottom: 8), - child: BackButton( - onPressed: () => ref.watch(routerProvider).pop(), - ), - ), - titleSpacing: 0, - title: Padding( - padding: const EdgeInsets.only(bottom: 8, right: 16), - child: ClipRRect( - borderRadius: BorderRadius.circular(50), - child: TextFormField( - controller: ref.watch(searchBookmarksProvider).searchController, - onChanged: (_) => ref.read(searchBookmarksProvider.notifier).notifyListeners(), - onEditingComplete: () { - FocusManager.instance.primaryFocus?.unfocus(); - ref.read(searchBookmarksProvider.notifier).setSearchTerm(); - ref.read(searchBookmarksProvider.notifier).setInitialLoadStatus(LoadStatus.loading); - ref.read(fetchSearchBookmarksProvider(provider.limit)); - }, - autofocus: true, - decoration: InputDecoration( - hintText: t.bookmarks.search.searchBookmarks, - prefixIcon: const Icon(Icons.search_rounded), - border: InputBorder.none, - filled: true, - fillColor: Colors.grey.withOpacity(0.2), - suffixIcon: ref.watch(searchBookmarksProvider).searchController.text != "" - ? IconButton( - onPressed: ref.read(searchBookmarksProvider.notifier).clearSearch, - icon: const Icon( - Icons.close_rounded, - size: 20, - ), - tooltip: t.bookmarks.search.clearSearch, - ) - : null, - contentPadding: const EdgeInsets.symmetric(vertical: 12), - ), - textInputAction: TextInputAction.search, - ), - ), - ), - ), - body: Builder( - builder: (context) { - if (provider.searchTerm == "") { - return EnterSearchTermScreen(message: t.bookmarks.search.inputSearchTerm); - } - - if (provider.inialLoadStatus == LoadStatus.loading) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - if (provider.inialLoadStatus == LoadStatus.error) { - return ErrorScreen( - error: t.bookmarks.search.cannotSearchError, - ); - } - - if (provider.bookmarks.isEmpty) { - return NoDataScreen( - message: t.bookmarks.search.inputtedSearchTermNoResults, - ); - } - - return NotificationListener( - onNotification: scrollListener, - child: ListView.builder( - itemCount: provider.loadingMore ? provider.bookmarks.length + 1 : provider.bookmarks.length, - itemBuilder: (context, index) { - if (provider.loadingMore == true && index == provider.bookmarks.length) { - return const Padding( - padding: EdgeInsets.all(16), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - return BookmarkItem( - bookmark: provider.bookmarks[index], - onSelect: (b) => ref.read(searchBookmarksProvider.notifier).selectBookmark(b, width), - onReadUnread: ref.read(searchBookmarksProvider.notifier).markAsReadUnread, - onDelete: (bookmark) => showDialog( - context: context, - builder: (context) => DeleteBookmarkModal( - bookmark: bookmark, - onDelete: ref.read(searchBookmarksProvider.notifier).deleteBookmark, - ), - ), - onArchiveUnarchive: ref.read(searchBookmarksProvider.notifier).archiveUnarchive, - onShareInternally: ref.read(searchBookmarksProvider.notifier).shareUnshare, - onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b), - selected: provider.bookmarks[index] == provider.selectedBookmark, - tabletMode: tabletMode, - ); - }, - ), - ); - }, - ), - ); - } -} diff --git a/lib/screens/bookmarks/ui/visualization_modal.dart b/lib/screens/bookmarks/ui/visualization_modal.dart deleted file mode 100644 index 2495991..0000000 --- a/lib/screens/bookmarks/ui/visualization_modal.dart +++ /dev/null @@ -1,141 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:segmented_button_slide/segmented_button_slide.dart'; - -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/widgets/section_label.dart'; - -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class VisualizationModal extends ConsumerWidget { - const VisualizationModal({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), - color: Theme.of(context).dialogBackgroundColor, - ), - child: SafeArea( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.sort_rounded, - color: Theme.of(context).colorScheme.secondary, - size: 24, - ), - const SizedBox(height: 16), - Text( - t.bookmarks.filterSort, - style: const TextStyle( - fontSize: 24, - ), - ), - const SizedBox(height: 8), - SectionLabel( - label: t.bookmarks.readStatus, - padding: const EdgeInsets.symmetric( - horizontal: 0, - vertical: 16, - ), - ), - SegmentedButtonSlide( - entries: [ - SegmentedButtonSlideEntry(label: t.bookmarks.all), - SegmentedButtonSlideEntry(label: t.bookmarks.unread), - SegmentedButtonSlideEntry(label: t.bookmarks.read), - ], - selectedEntry: ref.watch(bookmarksProvider).readStatus.index, - onChange: (v) => ref.read(bookmarksProvider.notifier).setReadStatus(ReadStatus.values[v]), - colors: SegmentedButtonSlideColors( - barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), - backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 8), - SectionLabel( - label: t.bookmarks.sorting, - padding: const EdgeInsets.symmetric( - horizontal: 0, - vertical: 16, - ), - ), - SegmentedButtonSlide( - entries: [ - SegmentedButtonSlideEntry(label: t.bookmarks.date, icon: Icons.schedule_rounded), - SegmentedButtonSlideEntry(label: t.bookmarks.title, icon: Icons.title_rounded), - ], - selectedEntry: ref.watch(bookmarksProvider).sortingType.index, - onChange: (v) => ref.read(bookmarksProvider.notifier).setSortingType(SortingType.values[v]), - colors: SegmentedButtonSlideColors( - barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), - backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 16), - SegmentedButtonSlide( - entries: [ - SegmentedButtonSlideEntry( - label: t.bookmarks.descendant, - icon: Icons.arrow_downward_rounded, - ), - SegmentedButtonSlideEntry( - label: t.bookmarks.ascendant, - icon: Icons.arrow_upward_rounded, - ), - ], - selectedEntry: ref.watch(bookmarksProvider).sortingWay.index, - onChange: (v) => ref.read(bookmarksProvider.notifier).setSortingWay(SortingWay.values[v]), - colors: SegmentedButtonSlideColors( - barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), - backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.only(top: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(t.generic.close), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/filtered_bookmarks/model/filtered_bookmarks.model.dart b/lib/screens/filtered_bookmarks/model/filtered_bookmarks.model.dart deleted file mode 100644 index 02ec4e1..0000000 --- a/lib/screens/filtered_bookmarks/model/filtered_bookmarks.model.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:go_router/go_router.dart'; - -import 'package:linkdy/config/options.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/models/data/tags.dart'; - -class FilteredBookmarksModel { - FilteredBookmarksMode filteredBookmarksMode; - String? tagId; - Tag? tag; - int currentPage; - int limit; - LoadStatus initialLoadStatus; - List bookmarks; - int maxNumber; - bool loadingMore; - Bookmark? selectedBookmark; - final GoRouter webViewRouter; - - FilteredBookmarksModel({ - this.filteredBookmarksMode = FilteredBookmarksMode.shared, - this.tagId, - this.tag, - this.currentPage = 0, - this.limit = ConfigOptions.listLimit, - this.initialLoadStatus = LoadStatus.loading, - required this.bookmarks, - this.maxNumber = 0, - this.loadingMore = false, - this.selectedBookmark, - required this.webViewRouter, - }); -} diff --git a/lib/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart b/lib/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart deleted file mode 100644 index b0c89af..0000000 --- a/lib/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart +++ /dev/null @@ -1,288 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/webview/ui/webview.dart'; -import 'package:linkdy/screens/bookmarks/provider/common_functions.dart'; -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/screens/filtered_bookmarks/model/filtered_bookmarks.model.dart'; -import 'package:linkdy/screens/webview/ui/invalid_bookmark.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/utils/open_url.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/data/tags.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -part 'filtered_bookmarks.provider.g.dart'; - -@riverpod -FutureOr tagBookmarksRequest(TagBookmarksRequestRef ref, Tag? tag, String? tagId, int limit) async { - final tagResult = tag == null ? await ref.read(apiClientProvider)!.fetchTagById(tagId!) : null; - if (tagResult != null && tagResult.successful == false) { - ref.read(filteredBookmarksProvider.notifier).setInitialLoadStatus(LoadStatus.error); - return; - } - - final bookmarksResult = await ref.read(apiClientProvider)!.fetchBookmarks( - q: tag != null ? "#${tag.name}" : tagResult!.content!.name, - limit: limit, - offset: 0, - ); - - if (bookmarksResult.successful == true) { - ref.read(filteredBookmarksProvider).bookmarks = bookmarksResult.content!.results!; - ref.read(filteredBookmarksProvider).maxNumber = bookmarksResult.content!.count!; - if (tag == null) ref.read(filteredBookmarksProvider).tag = tagResult!.content!; - ref.read(filteredBookmarksProvider).currentPage = 0; - ref.read(filteredBookmarksProvider).loadingMore = false; - ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.loaded; - } else { - ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.error; - } - - ref.read(filteredBookmarksProvider.notifier).notifyListeners(); -} - -@riverpod -FutureOr tagBookmarksRequestLoadMore(FilteredBookmarksRequestLoadMoreRef ref) async { - final provider = ref.read(filteredBookmarksProvider); - - final newOffset = provider.limit * (provider.currentPage + 1); - - final result = await ref.read(apiClientProvider)!.fetchBookmarks( - q: provider.tag!.name, - limit: provider.limit, - offset: newOffset, - ); - - if (result.successful == true) { - provider.bookmarks = [...provider.bookmarks, ...result.content!.results!]; - provider.maxNumber = result.content!.count!; - provider.currentPage = provider.currentPage + 1; - } - - ref.read(filteredBookmarksProvider.notifier).setLoadingMore(false); -} - -@riverpod -FutureOr filteredBookmarksRequest(FilteredBookmarksRequestRef ref, FilteredBookmarksMode mode, int limit) async { - final bookmarksResult = mode == FilteredBookmarksMode.shared - ? await ref.read(apiClientProvider)!.fetchSharedBookmarks( - limit: limit, - offset: 0, - ) - : await ref.read(apiClientProvider)!.fetchArchivedBookmarks( - limit: limit, - offset: 0, - ); - - if (bookmarksResult.successful == true) { - ref.read(filteredBookmarksProvider).bookmarks = bookmarksResult.content!.results!; - ref.read(filteredBookmarksProvider).maxNumber = bookmarksResult.content!.count!; - ref.read(filteredBookmarksProvider).currentPage = 0; - ref.read(filteredBookmarksProvider).loadingMore = false; - ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.loaded; - } else { - ref.read(filteredBookmarksProvider).initialLoadStatus = LoadStatus.error; - } - - ref.read(filteredBookmarksProvider.notifier).notifyListeners(); -} - -@riverpod -FutureOr filteredBookmarksRequestLoadMore(TagBookmarksRequestLoadMoreRef ref) async { - final provider = ref.read(filteredBookmarksProvider); - - final newOffset = provider.limit * (provider.currentPage + 1); - - final result = ref.read(filteredBookmarksProvider).filteredBookmarksMode == FilteredBookmarksMode.shared - ? await ref.read(apiClientProvider)!.fetchSharedBookmarks( - q: provider.tag!.name, - limit: provider.limit, - offset: newOffset, - ) - : await ref.read(apiClientProvider)!.fetchArchivedBookmarks( - q: provider.tag!.name, - limit: provider.limit, - offset: newOffset, - ); - - if (result.successful == true) { - provider.bookmarks = [...provider.bookmarks, ...result.content!.results!]; - provider.maxNumber = result.content!.count!; - provider.currentPage = provider.currentPage + 1; - } - - ref.read(filteredBookmarksProvider.notifier).setLoadingMore(false); -} - -const _webViewRoute = "wb"; -const _webViewRoutePath = "/wb"; - -@riverpod -class FilteredBookmarks extends _$FilteredBookmarks { - @override - FilteredBookmarksModel build() { - return FilteredBookmarksModel( - bookmarks: [], - webViewRouter: GoRouter( - routes: [ - GoRoute( - path: "/", - builder: (context, state) => const SizedBox(), - routes: [ - GoRoute( - path: _webViewRoute, - pageBuilder: (context, state) { - final extra = state.extra; - if (extra is Bookmark) { - return CustomTransitionPage( - child: WebViewScreen(bookmark: extra), - transitionsBuilder: (context, animation, secondaryAnimation, child) => child, - ); - } else { - return CustomTransitionPage( - child: const InvalidBookmarkScreen(), - transitionsBuilder: (context, animation, secondaryAnimation, child) => child, - ); - } - }, - ), - ], - ), - ], - ), - ); - } - - void setMode(FilteredBookmarksMode mode) { - state.filteredBookmarksMode = mode; - } - - void setCurrentPage(int page) { - state.currentPage = page; - } - - void setLimit(int limit) { - state.limit = limit; - } - - void setInitialLoadStatus(LoadStatus status) { - state.initialLoadStatus = status; - ref.notifyListeners(); - } - - void setLoadingMore(bool status) { - state.loadingMore = status; - ref.notifyListeners(); - } - - void clearSelectedBookmark() { - state.selectedBookmark = null; - ref.notifyListeners(); - } - - void selectBookmark(Bookmark bookmark, double width) { - if (ref.watch(appStatusProvider).openLinksBrowser == OpenLinksBrowser.browserCustomTab) { - openUrlCustomTab(bookmark.url!); - } else if (ref.watch(appStatusProvider).openLinksBrowser == OpenLinksBrowser.systemBrowser) { - openUrlSystemBrowser(bookmark.url!); - } else { - if (width <= Sizes.tabletBreakpoint) { - ref.watch(routerProvider).push(RoutesPaths.webview, extra: bookmark); - } else if (bookmark != state.selectedBookmark) { - state.webViewRouter.go(_webViewRoutePath, extra: bookmark); - } - state.selectedBookmark = bookmark; - ref.notifyListeners(); - } - } - - Future refresh() async { - if (state.filteredBookmarksMode == FilteredBookmarksMode.tag) { - await ref.read( - tagBookmarksRequestProvider(state.tag, state.tagId, state.limit).future, - ); - } else { - await ref.read( - filteredBookmarksRequestProvider(state.filteredBookmarksMode, state.limit).future, - ); - } - } - - void notifyListeners() { - ref.notifyListeners(); - } - - void deleteBookmark(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.deleteBookmark( - scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result == true) { - state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); - ref.notifyListeners(); - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.where((b) => b.id != bookmark.id).toList()); - } - } - - void markAsReadUnread(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.markAsReadUnread( - scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result != null) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); - ref.notifyListeners(); - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.map((b) => b.id == result.id ? result : b).toList()); - } - } - - void archiveUnarchive(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.archiveUnarchive( - scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result == true) { - state.bookmarks = state.bookmarks.where((b) => b.id != bookmark.id).toList(); - ref.notifyListeners(); - ref.read(bookmarksProvider.notifier).refresh(); - } - } - - void shareUnshare(Bookmark bookmark) async { - final result = await BookmarkCommonFunctions.shareUnshare( - scaffoldMessengerKey: ScaffoldMessengerKeys.filteredBookmarks, - ref: ref, - bookmark: bookmark, - apiClient: ref.read(apiClientProvider)!, - ); - if (result != null && state.filteredBookmarksMode == FilteredBookmarksMode.shared) { - state.bookmarks = state.bookmarks.where((b) => b.id != result.id).toList(); - } else if (result != null && state.filteredBookmarksMode != FilteredBookmarksMode.shared) { - state.bookmarks = state.bookmarks.map((b) => b.id == result.id ? result : b).toList(); - } - ref.notifyListeners(); - if (result != null) { - ref - .read(bookmarksProvider.notifier) - .setBookmarks(ref.read(bookmarksProvider).bookmarks.map((b) => b.id == result.id ? result : b).toList()); - } - } -} diff --git a/lib/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.g.dart b/lib/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.g.dart deleted file mode 100644 index e8b0c83..0000000 --- a/lib/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.g.dart +++ /dev/null @@ -1,392 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'filtered_bookmarks.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$tagBookmarksRequestHash() => - r'795205672ccd02914dbb2e15dbcf93bac94c645c'; - -/// Copied from Dart SDK -class _SystemHash { - _SystemHash._(); - - static int combine(int hash, int value) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + value); - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - // ignore: parameter_assignments - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - // ignore: parameter_assignments - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } -} - -/// See also [tagBookmarksRequest]. -@ProviderFor(tagBookmarksRequest) -const tagBookmarksRequestProvider = TagBookmarksRequestFamily(); - -/// See also [tagBookmarksRequest]. -class TagBookmarksRequestFamily extends Family> { - /// See also [tagBookmarksRequest]. - const TagBookmarksRequestFamily(); - - /// See also [tagBookmarksRequest]. - TagBookmarksRequestProvider call( - Tag? tag, - String? tagId, - int limit, - ) { - return TagBookmarksRequestProvider( - tag, - tagId, - limit, - ); - } - - @override - TagBookmarksRequestProvider getProviderOverride( - covariant TagBookmarksRequestProvider provider, - ) { - return call( - provider.tag, - provider.tagId, - provider.limit, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'tagBookmarksRequestProvider'; -} - -/// See also [tagBookmarksRequest]. -class TagBookmarksRequestProvider extends AutoDisposeFutureProvider { - /// See also [tagBookmarksRequest]. - TagBookmarksRequestProvider( - Tag? tag, - String? tagId, - int limit, - ) : this._internal( - (ref) => tagBookmarksRequest( - ref as TagBookmarksRequestRef, - tag, - tagId, - limit, - ), - from: tagBookmarksRequestProvider, - name: r'tagBookmarksRequestProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$tagBookmarksRequestHash, - dependencies: TagBookmarksRequestFamily._dependencies, - allTransitiveDependencies: - TagBookmarksRequestFamily._allTransitiveDependencies, - tag: tag, - tagId: tagId, - limit: limit, - ); - - TagBookmarksRequestProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.tag, - required this.tagId, - required this.limit, - }) : super.internal(); - - final Tag? tag; - final String? tagId; - final int limit; - - @override - Override overrideWith( - FutureOr Function(TagBookmarksRequestRef provider) create, - ) { - return ProviderOverride( - origin: this, - override: TagBookmarksRequestProvider._internal( - (ref) => create(ref as TagBookmarksRequestRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - tag: tag, - tagId: tagId, - limit: limit, - ), - ); - } - - @override - AutoDisposeFutureProviderElement createElement() { - return _TagBookmarksRequestProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is TagBookmarksRequestProvider && - other.tag == tag && - other.tagId == tagId && - other.limit == limit; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, tag.hashCode); - hash = _SystemHash.combine(hash, tagId.hashCode); - hash = _SystemHash.combine(hash, limit.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin TagBookmarksRequestRef on AutoDisposeFutureProviderRef { - /// The parameter `tag` of this provider. - Tag? get tag; - - /// The parameter `tagId` of this provider. - String? get tagId; - - /// The parameter `limit` of this provider. - int get limit; -} - -class _TagBookmarksRequestProviderElement - extends AutoDisposeFutureProviderElement with TagBookmarksRequestRef { - _TagBookmarksRequestProviderElement(super.provider); - - @override - Tag? get tag => (origin as TagBookmarksRequestProvider).tag; - @override - String? get tagId => (origin as TagBookmarksRequestProvider).tagId; - @override - int get limit => (origin as TagBookmarksRequestProvider).limit; -} - -String _$tagBookmarksRequestLoadMoreHash() => - r'36205474b3c1d3f18f31af56cc97c700f328a4bc'; - -/// See also [tagBookmarksRequestLoadMore]. -@ProviderFor(tagBookmarksRequestLoadMore) -final tagBookmarksRequestLoadMoreProvider = - AutoDisposeFutureProvider.internal( - tagBookmarksRequestLoadMore, - name: r'tagBookmarksRequestLoadMoreProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$tagBookmarksRequestLoadMoreHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef TagBookmarksRequestLoadMoreRef = AutoDisposeFutureProviderRef; -String _$filteredBookmarksRequestHash() => - r'f5352c5076d8bf2ed0cf738bdc0c0cffc9d18a25'; - -/// See also [filteredBookmarksRequest]. -@ProviderFor(filteredBookmarksRequest) -const filteredBookmarksRequestProvider = FilteredBookmarksRequestFamily(); - -/// See also [filteredBookmarksRequest]. -class FilteredBookmarksRequestFamily extends Family> { - /// See also [filteredBookmarksRequest]. - const FilteredBookmarksRequestFamily(); - - /// See also [filteredBookmarksRequest]. - FilteredBookmarksRequestProvider call( - FilteredBookmarksMode mode, - int limit, - ) { - return FilteredBookmarksRequestProvider( - mode, - limit, - ); - } - - @override - FilteredBookmarksRequestProvider getProviderOverride( - covariant FilteredBookmarksRequestProvider provider, - ) { - return call( - provider.mode, - provider.limit, - ); - } - - static const Iterable? _dependencies = null; - - @override - Iterable? get dependencies => _dependencies; - - static const Iterable? _allTransitiveDependencies = null; - - @override - Iterable? get allTransitiveDependencies => - _allTransitiveDependencies; - - @override - String? get name => r'filteredBookmarksRequestProvider'; -} - -/// See also [filteredBookmarksRequest]. -class FilteredBookmarksRequestProvider extends AutoDisposeFutureProvider { - /// See also [filteredBookmarksRequest]. - FilteredBookmarksRequestProvider( - FilteredBookmarksMode mode, - int limit, - ) : this._internal( - (ref) => filteredBookmarksRequest( - ref as FilteredBookmarksRequestRef, - mode, - limit, - ), - from: filteredBookmarksRequestProvider, - name: r'filteredBookmarksRequestProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') - ? null - : _$filteredBookmarksRequestHash, - dependencies: FilteredBookmarksRequestFamily._dependencies, - allTransitiveDependencies: - FilteredBookmarksRequestFamily._allTransitiveDependencies, - mode: mode, - limit: limit, - ); - - FilteredBookmarksRequestProvider._internal( - super._createNotifier, { - required super.name, - required super.dependencies, - required super.allTransitiveDependencies, - required super.debugGetCreateSourceHash, - required super.from, - required this.mode, - required this.limit, - }) : super.internal(); - - final FilteredBookmarksMode mode; - final int limit; - - @override - Override overrideWith( - FutureOr Function(FilteredBookmarksRequestRef provider) create, - ) { - return ProviderOverride( - origin: this, - override: FilteredBookmarksRequestProvider._internal( - (ref) => create(ref as FilteredBookmarksRequestRef), - from: from, - name: null, - dependencies: null, - allTransitiveDependencies: null, - debugGetCreateSourceHash: null, - mode: mode, - limit: limit, - ), - ); - } - - @override - AutoDisposeFutureProviderElement createElement() { - return _FilteredBookmarksRequestProviderElement(this); - } - - @override - bool operator ==(Object other) { - return other is FilteredBookmarksRequestProvider && - other.mode == mode && - other.limit == limit; - } - - @override - int get hashCode { - var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, mode.hashCode); - hash = _SystemHash.combine(hash, limit.hashCode); - - return _SystemHash.finish(hash); - } -} - -mixin FilteredBookmarksRequestRef on AutoDisposeFutureProviderRef { - /// The parameter `mode` of this provider. - FilteredBookmarksMode get mode; - - /// The parameter `limit` of this provider. - int get limit; -} - -class _FilteredBookmarksRequestProviderElement - extends AutoDisposeFutureProviderElement - with FilteredBookmarksRequestRef { - _FilteredBookmarksRequestProviderElement(super.provider); - - @override - FilteredBookmarksMode get mode => - (origin as FilteredBookmarksRequestProvider).mode; - @override - int get limit => (origin as FilteredBookmarksRequestProvider).limit; -} - -String _$filteredBookmarksRequestLoadMoreHash() => - r'a40280a01fcfa3892c76287a5e67e5ab9cc00cd5'; - -/// See also [filteredBookmarksRequestLoadMore]. -@ProviderFor(filteredBookmarksRequestLoadMore) -final filteredBookmarksRequestLoadMoreProvider = - AutoDisposeFutureProvider.internal( - filteredBookmarksRequestLoadMore, - name: r'filteredBookmarksRequestLoadMoreProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$filteredBookmarksRequestLoadMoreHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef FilteredBookmarksRequestLoadMoreRef - = AutoDisposeFutureProviderRef; -String _$filteredBookmarksHash() => r'8f5229e1bb6b0d50c7df4fcb6c3ef6c2aab898af'; - -/// See also [FilteredBookmarks]. -@ProviderFor(FilteredBookmarks) -final filteredBookmarksProvider = AutoDisposeNotifierProvider.internal( - FilteredBookmarks.new, - name: r'filteredBookmarksProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$filteredBookmarksHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$FilteredBookmarks = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/filtered_bookmarks/ui/filtered_bookmarks.dart b/lib/screens/filtered_bookmarks/ui/filtered_bookmarks.dart deleted file mode 100644 index d26112c..0000000 --- a/lib/screens/filtered_bookmarks/ui/filtered_bookmarks.dart +++ /dev/null @@ -1,247 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -import 'package:linkdy/screens/bookmarks/ui/bookmark_form_modal.dart'; -import 'package:linkdy/widgets/bookmark_item/bookmark_item.dart'; -import 'package:linkdy/screens/bookmarks/ui/delete_bookmark_modal.dart'; -import 'package:linkdy/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart'; -import 'package:linkdy/widgets/error_screen.dart'; -import 'package:linkdy/widgets/no_data_screen.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/models/data/tags.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class FilteredBookmarksScreen extends HookConsumerWidget { - final FilteredBookmarksMode filteredBookmarksMode; - final String? tagId; - final Tag? tag; - - const FilteredBookmarksScreen({ - super.key, - required this.filteredBookmarksMode, - this.tagId, - this.tag, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - useEffect( - () { - ref.read(filteredBookmarksProvider.notifier).setMode(filteredBookmarksMode); - if (filteredBookmarksMode == FilteredBookmarksMode.tag) { - if (tag == null && tagId == null) { - final router = ref.read(routerProvider); - while (router.canPop() == true) { - router.pop(); - } - router.pushReplacement(RoutesPaths.bookmarks); - return; - } - if (tag != null) { - ref.read(filteredBookmarksProvider).tag = tag; - } - if (tagId != null) { - ref.read(filteredBookmarksProvider).tagId = tagId; - } - ref.read(tagBookmarksRequestProvider(tag, tagId, ref.read(filteredBookmarksProvider).limit)); - } else { - ref.read( - filteredBookmarksRequestProvider(filteredBookmarksMode, ref.read(filteredBookmarksProvider).limit), - ); - } - return null; - }, - [filteredBookmarksMode, tagId, tag], - ); - - if (filteredBookmarksMode == FilteredBookmarksMode.tag && tag == null && tagId == null) { - return const Material(); - } - - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.filteredBookmarks, - child: LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth > Sizes.tabletBreakpoint) { - return Material( - child: Row( - children: [ - Expanded( - flex: 2, - child: _List( - filteredBookmarksMode: filteredBookmarksMode, - tag: tag, - tabletMode: true, - ), - ), - Expanded( - flex: 3, - child: Material( - child: Router.withConfig(config: ref.watch(filteredBookmarksProvider).webViewRouter), - ), - ), - ], - ), - ); - } else { - return _List( - filteredBookmarksMode: filteredBookmarksMode, - tag: tag, - tabletMode: false, - ); - } - }, - ), - ); - } -} - -class _List extends ConsumerWidget { - final bool tabletMode; - final FilteredBookmarksMode filteredBookmarksMode; - final Tag? tag; - - const _List({ - required this.filteredBookmarksMode, - this.tag, - required this.tabletMode, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final provider = ref.watch(filteredBookmarksProvider); - - final width = MediaQuery.of(context).size.width; - - bool scrollListener(ScrollUpdateNotification scrollNotification) { - if (scrollNotification.metrics.extentAfter < 100 && - provider.loadingMore == false && - provider.bookmarks.length < provider.maxNumber) { - ref.read(filteredBookmarksProvider.notifier).setLoadingMore(true); - ref.read(tagBookmarksRequestLoadMoreProvider); - } - return false; - } - - String title() { - switch (filteredBookmarksMode) { - case FilteredBookmarksMode.tag: - return tag != null - ? "#${tag!.name}" - : provider.tag != null - ? "#${provider.tag!.name}" - : ''; - - case FilteredBookmarksMode.archived: - return t.bookmarks.archived; - - case FilteredBookmarksMode.shared: - return t.bookmarks.shared; - } - } - - String noContent() { - switch (filteredBookmarksMode) { - case FilteredBookmarksMode.tag: - return t.tags.filteredBookmarks.noBookmarksWithThisTag; - - case FilteredBookmarksMode.archived: - return t.tags.filteredBookmarks.noArchivedBookmarks; - - case FilteredBookmarksMode.shared: - return t.tags.filteredBookmarks.noSharedBookmarks; - } - } - - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(title()), - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => RefreshIndicator( - displacement: 120, - onRefresh: () => ref.read(filteredBookmarksProvider.notifier).refresh(), - child: NotificationListener( - onNotification: scrollListener, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (provider.initialLoadStatus == LoadStatus.loading) - const SliverFillRemaining( - child: Center(child: CircularProgressIndicator()), - ), - if (provider.initialLoadStatus == LoadStatus.error) - SliverFillRemaining( - child: ErrorScreen( - error: t.bookmarks.cannotLoadBookmarks, - ), - ), - if (provider.bookmarks.isEmpty) - SliverFillRemaining( - child: NoDataScreen( - message: noContent(), - ), - ), - if (provider.bookmarks.isNotEmpty) - SliverList.builder( - itemCount: - provider.loadingMore == true ? provider.bookmarks.length + 1 : provider.bookmarks.length, - itemBuilder: (context, index) { - if (provider.loadingMore == true && index == provider.bookmarks.length) { - return const Padding( - padding: EdgeInsets.all(16), - child: Center( - child: CircularProgressIndicator(), - ), - ); - } - return BookmarkItem( - bookmark: provider.bookmarks[index], - onSelect: (b) => ref.read(filteredBookmarksProvider.notifier).selectBookmark(b, width), - onReadUnread: ref.read(filteredBookmarksProvider.notifier).markAsReadUnread, - onDelete: (bookmark) => showDialog( - context: context, - builder: (context) => DeleteBookmarkModal( - bookmark: bookmark, - onDelete: ref.read(filteredBookmarksProvider.notifier).deleteBookmark, - ), - ), - onArchiveUnarchive: ref.read(filteredBookmarksProvider.notifier).archiveUnarchive, - onShareInternally: ref.read(filteredBookmarksProvider.notifier).shareUnshare, - onEdit: (b) => openBookmarkFormModal(context: context, width: width, bookmark: b), - selected: provider.bookmarks[index] == provider.selectedBookmark, - tabletMode: tabletMode, - ); - }, - ), - ], - ), - ), - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/onboarding/model/connect.model.dart b/lib/screens/onboarding/model/connect.model.dart deleted file mode 100644 index 58cac86..0000000 --- a/lib/screens/onboarding/model/connect.model.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:linkdy/constants/enums.dart'; - -class ConnectModel { - bool isConnecting; - int method; - final TextEditingController ipDomainController; - String? ipDomainError; - final TextEditingController portController; - String? portError; - final TextEditingController pathController; - String? pathError; - final TextEditingController tokenController; - String? tokenError; - bool validValues; - LoadStatus? testConnection; - - ConnectModel({ - this.isConnecting = false, - this.method = 0, - required this.ipDomainController, - this.ipDomainError, - required this.portController, - this.portError, - required this.pathController, - this.pathError, - required this.tokenController, - this.tokenError, - this.validValues = true, - this.testConnection, - }); -} diff --git a/lib/screens/onboarding/model/onboarding.model.dart b/lib/screens/onboarding/model/onboarding.model.dart deleted file mode 100644 index 6657cb5..0000000 --- a/lib/screens/onboarding/model/onboarding.model.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/material.dart'; - -class OnboardingModel { - final PageController pageController; - bool confirmServerRunning; - - OnboardingModel({ - required this.pageController, - this.confirmServerRunning = false, - }); -} diff --git a/lib/screens/onboarding/provider/connect.provider.dart b/lib/screens/onboarding/provider/connect.provider.dart deleted file mode 100644 index e3147bf..0000000 --- a/lib/screens/onboarding/provider/connect.provider.dart +++ /dev/null @@ -1,173 +0,0 @@ -import 'package:dio/dio.dart'; -import 'package:flutter/material.dart'; -import 'package:uuid/uuid.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/onboarding/model/connect.model.dart'; - -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/utils/snackbar.dart'; -import 'package:linkdy/providers/dio_interceptor.provider.dart'; -import 'package:linkdy/providers/server_instances.provider.dart'; -import 'package:linkdy/utils/api_base_url.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/utils/process_modal.dart'; -import 'package:linkdy/models/server_instance.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; -import 'package:linkdy/services/api_client.dart'; -import 'package:linkdy/constants/regexp.dart'; - -part 'connect.provider.g.dart'; - -const uuid = Uuid(); - -@riverpod -class Connect extends _$Connect { - @override - ConnectModel build() { - return ConnectModel( - isConnecting: false, - method: 0, - ipDomainController: TextEditingController(), - ipDomainError: null, - portController: TextEditingController(), - portError: null, - pathController: TextEditingController(), - pathError: null, - tokenController: TextEditingController(), - tokenError: null, - validValues: false, - ); - } - - void setConnectionMethod(int method) { - state.testConnection = null; - state.method = method; - ref.notifyListeners(); - } - - void validateIpDomain(String value) { - state.testConnection = null; - if (value != "") { - state.ipDomainError = null; - } else { - state.ipDomainError = t.onboarding.invalidIpDomain; - } - state.validValues = validValues(); - ref.notifyListeners(); - } - - void validatePort(String value) { - state.testConnection = null; - if (value != '') { - if (int.tryParse(value) != null && int.parse(value) <= 65535) { - state.portError = null; - } else { - state.portError = t.onboarding.invalidPort; - } - } - state.validValues = validValues(); - ref.notifyListeners(); - } - - void validatePath(String value) { - state.testConnection = null; - if (value == "") { - state.pathError = null; - } else { - if (Regexps.path.hasMatch(value) == true) { - state.pathError = null; - } else { - state.pathError = t.onboarding.invalidPath; - } - } - state.validValues = validValues(); - ref.notifyListeners(); - } - - void validateToken(String value) { - state.testConnection = null; - if (value != "") { - state.tokenError = null; - } else { - state.tokenError = t.onboarding.tokenRequired; - } - state.validValues = validValues(); - ref.notifyListeners(); - } - - bool validValues() { - return state.tokenController.text != "" && - state.tokenError == null && - state.ipDomainController.text != "" && - state.ipDomainError == null && - state.pathError == null && - state.portError == null; - } - - void testConnection() async { - state.testConnection = LoadStatus.loading; - ref.notifyListeners(); - - final connectionString = - "${ConnectionMethod.values[state.method].name}://${state.ipDomainController.text}${state.portController.text != '' ? ':${state.portController.text}' : ""}${state.pathController.text}"; - final result = await testServerReachability(connectionString); - - if (result == true) { - state.testConnection = LoadStatus.loaded; - } else { - state.testConnection = LoadStatus.error; - } - ref.notifyListeners(); - } -} - -@riverpod -FutureOr connectToServer(ConnectToServerRef ref) async { - final serverInstance = ServerInstance( - id: uuid.v4(), - method: ConnectionMethod.values[ref.watch(connectProvider).method].name, - ipDomain: ref.watch(connectProvider).ipDomainController.text, - token: ref.watch(connectProvider).tokenController.text, - path: ref.watch(connectProvider).pathController.text, - port: int.tryParse(ref.watch(connectProvider).portController.text), - ); - - final apiClient = ApiClientService( - serverInstance: serverInstance, - dioInstance: Dio( - BaseOptions( - baseUrl: apiBaseUrl(serverInstance), - headers: { - "Authorization": "Token ${serverInstance.token}", - }, - ), - )..interceptors.add(ref.watch(dioInterceptorProvider)), - ); - - final processModal = ProcessModal(); - processModal.open(t.onboarding.connecting); - - final result = await apiClient.checkConnectionInstance(); - - processModal.close(); - if (result == AuthResult.success) { - ref.read(apiClientProvider.notifier).setApiClient(apiClient); - ref.read(serverInstancesProvider.notifier).saveNewInstance(serverInstance); - } else if (result == AuthResult.invalidToken) { - showSnackbar( - key: ScaffoldMessengerKeys.onboarding, - label: t.onboarding.invalidToken, - color: Colors.red, - ); - } else { - showSnackbar( - key: ScaffoldMessengerKeys.onboarding, - label: t.onboarding.cannotConnectToServer, - color: Colors.red, - ); - } - - return false; -} diff --git a/lib/screens/onboarding/provider/connect.provider.g.dart b/lib/screens/onboarding/provider/connect.provider.g.dart deleted file mode 100644 index eb338d2..0000000 --- a/lib/screens/onboarding/provider/connect.provider.g.dart +++ /dev/null @@ -1,40 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'connect.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$connectToServerHash() => r'4c7d8eb1e2ed082e5ce2cde03f8afe343d7126b9'; - -/// See also [connectToServer]. -@ProviderFor(connectToServer) -final connectToServerProvider = AutoDisposeFutureProvider.internal( - connectToServer, - name: r'connectToServerProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$connectToServerHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef ConnectToServerRef = AutoDisposeFutureProviderRef; -String _$connectHash() => r'15405d136ca9517c557e6a3e021a882213ee3be2'; - -/// See also [Connect]. -@ProviderFor(Connect) -final connectProvider = - AutoDisposeNotifierProvider.internal( - Connect.new, - name: r'connectProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$connectHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$Connect = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/onboarding/provider/onboarding.provider.dart b/lib/screens/onboarding/provider/onboarding.provider.dart deleted file mode 100644 index 783e59a..0000000 --- a/lib/screens/onboarding/provider/onboarding.provider.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/onboarding/model/onboarding.model.dart'; - -part 'onboarding.provider.g.dart'; - -@riverpod -class Onboarding extends _$Onboarding { - @override - OnboardingModel build() { - return OnboardingModel( - pageController: PageController(), - confirmServerRunning: false, - ); - } - - void nextPage() { - state.pageController.nextPage( - duration: const Duration(milliseconds: 200), - curve: Curves.ease, - ); - } - - void previousPage() { - state.pageController.previousPage( - duration: const Duration(milliseconds: 200), - curve: Curves.ease, - ); - } - - void confirmServerRunning() { - state.confirmServerRunning = !state.confirmServerRunning; - ref.notifyListeners(); - } -} diff --git a/lib/screens/onboarding/provider/onboarding.provider.g.dart b/lib/screens/onboarding/provider/onboarding.provider.g.dart deleted file mode 100644 index d31fd60..0000000 --- a/lib/screens/onboarding/provider/onboarding.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'onboarding.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$onboardingHash() => r'06f4c2d233d6babdd1d8fef05e5a6285e19ec453'; - -/// See also [Onboarding]. -@ProviderFor(Onboarding) -final onboardingProvider = - AutoDisposeNotifierProvider.internal( - Onboarding.new, - name: r'onboardingProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$onboardingHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$Onboarding = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/onboarding/ui/connect.dart b/lib/screens/onboarding/ui/connect.dart deleted file mode 100644 index b4a833c..0000000 --- a/lib/screens/onboarding/ui/connect.dart +++ /dev/null @@ -1,253 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:segmented_button_slide/segmented_button_slide.dart'; - -import 'package:linkdy/screens/onboarding/ui/sliver_top_bar.dart'; -import 'package:linkdy/screens/onboarding/provider/connect.provider.dart'; -import 'package:linkdy/screens/onboarding/provider/onboarding.provider.dart'; -import 'package:linkdy/widgets/section_label.dart'; - -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class OnboardingConnect extends ConsumerWidget { - const OnboardingConnect({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: CustomScrollView( - slivers: [ - SliverPersistentHeader( - pinned: true, - delegate: OnboardingSliverTopBar( - icon: Icons.login_rounded, - title: t.onboarding.createConnection, - ), - ), - SliverList.list( - children: const [ - _ConnectForm(), - ], - ), - ], - ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - FilledButton( - onPressed: () => ref.read(onboardingProvider.notifier).previousPage(), - child: Row( - children: [ - const Icon(Icons.arrow_back_rounded), - const SizedBox(width: 8), - Text(t.onboarding.previous), - ], - ), - ), - FilledButton.icon( - onPressed: ref.watch(connectProvider).validValues ? () => ref.read(connectToServerProvider) : null, - icon: const Icon(Icons.login_rounded), - label: Text(t.onboarding.connect), - ), - ], - ), - ], - ), - ); - } -} - -class _ConnectForm extends ConsumerWidget { - const _ConnectForm(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final provider = ref.watch(connectProvider); - - final connectionMethod = ConnectionMethod.values[provider.method]; - - final connectionString = - "${connectionMethod.name}://${provider.ipDomainController.text}${provider.portController.text != '' ? ':${provider.portController.text}' : ""}${provider.pathController.text}"; - - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Flexible( - child: Text( - t.onboarding.createConnectionSubtitle, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ], - ), - Container( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), - margin: const EdgeInsets.only(top: 30, left: 24, right: 24), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withOpacity(0.05), - borderRadius: BorderRadius.circular(30), - border: Border.all(color: Theme.of(context).colorScheme.primary), - ), - child: Text( - connectionString, - textAlign: TextAlign.center, - style: TextStyle(color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.w500), - ), - ), - SectionLabel( - label: t.onboarding.serverDetails, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 24), - ), - SegmentedButtonSlide( - entries: const [ - SegmentedButtonSlideEntry(label: "HTTP"), - SegmentedButtonSlideEntry(label: "HTTPS"), - ], - selectedEntry: provider.method, - onChange: ref.read(connectProvider.notifier).setConnectionMethod, - colors: SegmentedButtonSlideColors( - barColor: Theme.of(context).colorScheme.primary.withOpacity(0.2), - backgroundSelectedColor: Theme.of(context).colorScheme.primary, - foregroundSelectedColor: Theme.of(context).colorScheme.onPrimary, - foregroundUnselectedColor: Theme.of(context).colorScheme.onSurface, - hoverColor: Theme.of(context).colorScheme.onSurfaceVariant, - ), - textOverflow: TextOverflow.ellipsis, - fontSize: 14, - height: 40, - margin: const EdgeInsets.symmetric( - horizontal: 24, - ), - ), - const SizedBox(height: 30), - TextFormField( - controller: provider.ipDomainController, - onChanged: ref.read(connectProvider.notifier).validateIpDomain, - autocorrect: false, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.link_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - errorText: provider.ipDomainError, - labelText: t.onboarding.ipAddressOrDomain, - helperText: t.onboarding.required, - ), - ), - const SizedBox(height: 24), - TextFormField( - controller: provider.portController, - onChanged: ref.read(connectProvider.notifier).validatePort, - autocorrect: false, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.tag_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - errorText: provider.portError, - labelText: t.onboarding.port, - ), - ), - const SizedBox(height: 24), - TextFormField( - controller: provider.pathController, - onChanged: ref.read(connectProvider.notifier).validatePath, - autocorrect: false, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.route_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - errorText: provider.pathError, - labelText: t.onboarding.path, - ), - ), - SectionLabel( - label: t.onboarding.authentication, - padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 24), - ), - TextFormField( - controller: provider.tokenController, - onChanged: ref.read(connectProvider.notifier).validateToken, - autocorrect: false, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.key_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - errorText: provider.tokenError, - labelText: t.onboarding.token, - helperText: t.onboarding.required, - ), - obscureText: true, - ), - const SizedBox(height: 24), - ElevatedButton( - onPressed: provider.testConnection == null ? () => ref.read(connectProvider.notifier).testConnection() : null, - style: ButtonStyle( - foregroundColor: provider.testConnection == LoadStatus.loaded - ? const WidgetStatePropertyAll(Colors.green) - : provider.testConnection == LoadStatus.error - ? const WidgetStatePropertyAll(Colors.red) - : null, - backgroundColor: provider.testConnection == LoadStatus.loaded - ? WidgetStatePropertyAll(Colors.green.withOpacity(0.15)) - : provider.testConnection == LoadStatus.error - ? WidgetStatePropertyAll(Colors.red.withOpacity(0.15)) - : null, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (provider.testConnection == null) Text(t.bookmarks.addBookmark.validateUrl), - if (provider.testConnection == LoadStatus.loading) ...[ - const SizedBox( - width: 12, - height: 12, - child: CircularProgressIndicator( - strokeWidth: 2, - ), - ), - const SizedBox(width: 8), - Text(t.onboarding.testingConnection), - ], - if (provider.testConnection == LoadStatus.loaded) ...[ - const Icon(Icons.check_circle_rounded), - const SizedBox(width: 8), - Text(t.onboarding.connectionServerEstablished), - ], - if (provider.testConnection == LoadStatus.error) ...[ - const Icon(Icons.error_rounded), - const SizedBox(width: 8), - Text(t.onboarding.connectionServerFailed), - ], - ], - ), - ), - const SizedBox(height: 16), - ], - ); - } -} diff --git a/lib/screens/onboarding/ui/onboarding.dart b/lib/screens/onboarding/ui/onboarding.dart deleted file mode 100644 index a3954f3..0000000 --- a/lib/screens/onboarding/ui/onboarding.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/onboarding/provider/onboarding.provider.dart'; -import 'package:linkdy/screens/onboarding/ui/connect.dart'; -import 'package:linkdy/screens/onboarding/ui/server_required.dart'; -import 'package:linkdy/screens/onboarding/ui/welcome.dart'; -import 'package:linkdy/widgets/system_overlay_style.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/global_keys.dart'; - -class Onboarding extends ConsumerWidget { - const Onboarding({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return OverlayStyle( - child: ScaffoldMessenger( - key: ScaffoldMessengerKeys.onboarding, - child: Scaffold( - body: SafeArea( - child: LayoutBuilder( - builder: (context, constraints) { - return Center( - child: ConstrainedBox( - constraints: constraints.maxWidth > Sizes.tabletBreakpoint - ? BoxConstraints( - maxWidth: 500, - maxHeight: constraints.maxHeight > 800 ? 800 : constraints.maxHeight - 100, - ) - : const BoxConstraints.expand(), - child: Container( - decoration: constraints.maxWidth > Sizes.tabletBreakpoint - ? BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(28), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - spreadRadius: 5, - blurRadius: 7, - offset: const Offset(0, 3), // changes position of shadow - ), - ], - ) - : null, - child: PageView( - controller: ref.watch(onboardingProvider).pageController, - physics: const NeverScrollableScrollPhysics(), - children: const [ - OnboardingWelcome(), - OnboardingServerRequired(), - OnboardingConnect(), - ], - ), - ), - ), - ); - }, - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/onboarding/ui/server_required.dart b/lib/screens/onboarding/ui/server_required.dart deleted file mode 100644 index 4c1919f..0000000 --- a/lib/screens/onboarding/ui/server_required.dart +++ /dev/null @@ -1,126 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/flutter_svg.dart'; - -import 'package:linkdy/screens/onboarding/provider/onboarding.provider.dart'; -import 'package:linkdy/screens/onboarding/ui/sliver_top_bar.dart'; - -import 'package:linkdy/constants/urls.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/utils/open_url.dart'; - -class OnboardingServerRequired extends ConsumerWidget { - const OnboardingServerRequired({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Padding( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: CustomScrollView( - slivers: [ - SliverPersistentHeader( - pinned: true, - delegate: OnboardingSliverTopBar( - icon: Icons.dns_rounded, - title: t.onboarding.serverRequired, - ), - ), - SliverList.list( - children: [ - Text( - t.onboarding.serverRequiredDescription, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 16), - Card( - child: InkWell( - onTap: () => openUrlCustomTab(Urls.linkdingInstallationInstructions), - borderRadius: BorderRadius.circular(10), - child: Padding( - padding: const EdgeInsets.all(24), - child: Row( - children: [ - SvgPicture.asset( - 'assets/resources/github.svg', - color: Theme.of(context).colorScheme.primary, - width: 40, - height: 40, - ), - const SizedBox(width: 24), - Flexible( - child: Text( - t.onboarding.installationInstructions, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ), - ), - ), - const SizedBox(height: 16), - ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), - leading: Checkbox( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), - ), - value: ref.watch(onboardingProvider).confirmServerRunning, - onChanged: (_) => ref.read(onboardingProvider.notifier).confirmServerRunning(), - ), - title: Text( - t.onboarding.serverRunningConfirmation, - style: const TextStyle(fontSize: 14), - ), - onTap: () => ref.read(onboardingProvider.notifier).confirmServerRunning(), - ), - ], - ), - ], - ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - FilledButton( - onPressed: () => ref.read(onboardingProvider.notifier).previousPage(), - child: Row( - children: [ - const Icon(Icons.arrow_back_rounded), - const SizedBox(width: 8), - Text(t.onboarding.previous), - ], - ), - ), - FilledButton( - onPressed: ref.watch(onboardingProvider).confirmServerRunning == true - ? () => ref.read(onboardingProvider.notifier).nextPage() - : null, - child: Row( - children: [ - Text(t.onboarding.next), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded), - ], - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/lib/screens/onboarding/ui/sliver_top_bar.dart b/lib/screens/onboarding/ui/sliver_top_bar.dart deleted file mode 100644 index b4fa78d..0000000 --- a/lib/screens/onboarding/ui/sliver_top_bar.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'package:flutter/material.dart'; - -const _minExent = 50.0; -const _maxExent = 130.0; - -const _iconMaxSize = 50; -const _iconMinSize = 30; - -const _textMaxSize = 28; -const _textMinSize = 22; - -const _textMaxTopPosition = 70; -const _textMinTopPosition = 0; - -const _textMaxLeftPosition = 0; -const _textMinLeftPosition = 44; - -class OnboardingSliverTopBar extends SliverPersistentHeaderDelegate { - final IconData icon; - final String title; - - const OnboardingSliverTopBar({ - required this.icon, - required this.title, - }); - - @override - Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - final iconPercentage = shrinkOffset.clamp(0, _maxExent - _minExent) / (_maxExent - _minExent); - final textPercentage = shrinkOffset.clamp(0, _maxExent - _minExent) / (_maxExent - _minExent); - - final iconSize = _iconMinSize + (_iconMaxSize - _iconMinSize) * (1 - iconPercentage); - final textSize = _textMinSize + (_textMaxSize - _textMinSize) * (1 - textPercentage); - final textTopPosition = _textMinTopPosition + (_textMaxTopPosition - _textMinTopPosition) * (1 - textPercentage); - final textLeftPosition = - _textMinLeftPosition + (_textMaxLeftPosition - _textMinLeftPosition) * (1 - textPercentage); - - return Container( - color: Theme.of(context).colorScheme.surface, - child: Stack( - children: [ - Positioned( - top: 0, - child: Icon( - icon, - size: iconSize, - color: Theme.of(context).colorScheme.primary, - ), - ), - Positioned( - top: textTopPosition, - left: textLeftPosition, - child: Text( - title, - style: TextStyle(fontSize: textSize), - ), - ), - ], - ), - ); - } - - @override - double get maxExtent => _maxExent; - - @override - double get minExtent => _minExent; - - @override - bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { - return false; - } -} diff --git a/lib/screens/onboarding/ui/welcome.dart b/lib/screens/onboarding/ui/welcome.dart deleted file mode 100644 index afaf93a..0000000 --- a/lib/screens/onboarding/ui/welcome.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -import 'package:linkdy/screens/onboarding/provider/onboarding.provider.dart'; - -class OnboardingWelcome extends ConsumerWidget { - const OnboardingWelcome({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.all(24), - child: Stack( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - 'assets/icon/icon1024.png', - width: 50, - height: 50, - ), - const SizedBox(height: 24), - Text( - t.onboarding.title, - style: const TextStyle(fontSize: 28), - ), - const SizedBox(height: 16), - Text( - t.onboarding.subtitle, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const SizedBox(), - FilledButton( - onPressed: () => ref.read(onboardingProvider.notifier).nextPage(), - child: Row( - children: [ - Text(t.onboarding.start), - const SizedBox(width: 8), - const Icon(Icons.arrow_forward_rounded), - ], - ), - ), - ], - ), - ], - ), - Center( - child: Transform.rotate( - angle: 0.7, - child: Icon( - Icons.link_rounded, - size: constraints.maxWidth > constraints.maxHeight - ? constraints.maxHeight - : constraints.maxWidth - 48, - color: Theme.of(context).colorScheme.secondary.withOpacity(0.2), - ), - ), - ), - ], - ), - ); - }, - ); - } -} diff --git a/lib/screens/settings/model/customization.model.dart b/lib/screens/settings/model/customization.model.dart deleted file mode 100644 index 70b942a..0000000 --- a/lib/screens/settings/model/customization.model.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomizationModel { - ScrollController? scrollController; - int? selectedScreen; - - CustomizationModel({ - this.scrollController, - this.selectedScreen, - }); -} diff --git a/lib/screens/settings/model/settings.model.dart b/lib/screens/settings/model/settings.model.dart deleted file mode 100644 index e806cf6..0000000 --- a/lib/screens/settings/model/settings.model.dart +++ /dev/null @@ -1,7 +0,0 @@ -class SettingsModel { - int? selectedScreen; - - SettingsModel({ - this.selectedScreen, - }); -} diff --git a/lib/screens/settings/provider/customization.provider.dart b/lib/screens/settings/provider/customization.provider.dart deleted file mode 100644 index dffbc2c..0000000 --- a/lib/screens/settings/provider/customization.provider.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/settings/model/customization.model.dart'; - -part 'customization.provider.g.dart'; - -@riverpod -class Customization extends _$Customization { - @override - CustomizationModel build() { - return CustomizationModel( - scrollController: ScrollController(), - ); - } -} diff --git a/lib/screens/settings/provider/customization.provider.g.dart b/lib/screens/settings/provider/customization.provider.g.dart deleted file mode 100644 index 4e68ffa..0000000 --- a/lib/screens/settings/provider/customization.provider.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'customization.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$customizationHash() => r'c4cf4b566abbe697ec14c5024e1576f230d3e9fb'; - -/// See also [Customization]. -@ProviderFor(Customization) -final customizationProvider = - AutoDisposeNotifierProvider.internal( - Customization.new, - name: r'customizationProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$customizationHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$Customization = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/settings/provider/settings.provider.dart b/lib/screens/settings/provider/settings.provider.dart deleted file mode 100644 index 9842f32..0000000 --- a/lib/screens/settings/provider/settings.provider.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/settings/model/settings.model.dart'; - -part 'settings.provider.g.dart'; - -@riverpod -class Settings extends _$Settings { - @override - SettingsModel build() { - return SettingsModel(); - } - - void setSelectedScreen(int screen) { - state.selectedScreen = screen; - ref.notifyListeners(); - } -} diff --git a/lib/screens/settings/provider/settings.provider.g.dart b/lib/screens/settings/provider/settings.provider.g.dart deleted file mode 100644 index 4a2fc62..0000000 --- a/lib/screens/settings/provider/settings.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'settings.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$settingsHash() => r'709696bfa70c1fa702132beb428561e073c7a620'; - -/// See also [Settings]. -@ProviderFor(Settings) -final settingsProvider = - AutoDisposeNotifierProvider.internal( - Settings.new, - name: r'settingsProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$settingsHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$Settings = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/settings/ui/customization/color_item.dart b/lib/screens/settings/ui/customization/color_item.dart deleted file mode 100644 index 9f36d94..0000000 --- a/lib/screens/settings/ui/customization/color_item.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:flutter/material.dart'; - -class ColorItem extends StatelessWidget { - final int index; - final int total; - final Color color; - final int numericValue; - final int? selectedValue; - final void Function(int) onChanged; - - const ColorItem({ - super.key, - required this.index, - required this.total, - required this.color, - required this.numericValue, - required this.selectedValue, - required this.onChanged, - }); - - @override - Widget build(BuildContext context) { - return Padding( - padding: index == 0 - ? const EdgeInsets.only(top: 10, right: 10, bottom: 10) - : index == total - 1 - ? const EdgeInsets.only(top: 10, bottom: 10, left: 10) - : const EdgeInsets.all(10), - child: Material( - borderRadius: BorderRadius.circular(50), - child: InkWell( - onTap: () => onChanged(numericValue), - borderRadius: BorderRadius.circular(50), - overlayColor: const WidgetStatePropertyAll(Colors.grey), - child: Container( - width: 50, - height: 50, - decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular(50), - ), - child: AnimatedOpacity( - opacity: numericValue == selectedValue ? 1 : 0, - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, - child: Icon( - Icons.check, - size: 30, - color: color.computeLuminance() > 0.5 ? Colors.black : Colors.white, - ), - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/settings/ui/customization/customization.dart b/lib/screens/settings/ui/customization/customization.dart deleted file mode 100644 index ad4f53e..0000000 --- a/lib/screens/settings/ui/customization/customization.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/settings/provider/customization.provider.dart'; -import 'package:linkdy/screens/settings/ui/customization/color_item.dart'; -import 'package:linkdy/screens/settings/ui/customization/theme_mode_button.dart'; -import 'package:linkdy/utils/color_translation.dart'; -import 'package:linkdy/widgets/custom_switch_list_tile.dart'; -import 'package:linkdy/widgets/section_label.dart'; - -import 'package:linkdy/constants/colors.dart'; -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; - -class Customization extends ConsumerWidget { - const Customization({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(t.settings.customization.customization), - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - SectionLabel( - label: t.settings.customization.theme, - padding: const EdgeInsets.only(top: 10, left: 16, right: 16, bottom: 5), - ), - Column( - children: [ - CustomSwitchListTile( - value: ref.watch(appStatusProvider).selectedTheme == SelectedTheme.system ? true : false, - onChanged: (value) => ref - .read(appStatusProvider.notifier) - .setTheme(value == true ? SelectedTheme.system : SelectedTheme.light), - title: t.settings.customization.systemDefined, - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ThemeModeButton( - icon: Icons.light_mode, - value: 1, - selected: ref.watch(appStatusProvider).selectedTheme.index, - label: t.settings.customization.light, - onChanged: (value) => - ref.read(appStatusProvider.notifier).setTheme(SelectedTheme.values[value]), - disabled: - ref.watch(appStatusProvider).selectedTheme == SelectedTheme.system ? true : false, - ), - ThemeModeButton( - icon: Icons.dark_mode, - value: 2, - selected: ref.watch(appStatusProvider).selectedTheme.index, - label: t.settings.customization.dark, - onChanged: (value) => - ref.read(appStatusProvider.notifier).setTheme(SelectedTheme.values[value]), - disabled: - ref.watch(appStatusProvider).selectedTheme == SelectedTheme.system ? true : false, - ), - ], - ), - ], - ), - SectionLabel( - label: t.settings.customization.color, - padding: const EdgeInsets.only(top: 45, left: 16, right: 16, bottom: 5), - ), - if (ref.watch(appStatusProvider).supportsDynamicTheme) - CustomSwitchListTile( - value: ref.watch(appStatusProvider).useDynamicTheme, - onChanged: ref.read(appStatusProvider.notifier).setUseDynamicTheme, - title: t.settings.customization.useDynamicTheme, - ), - if (ref.watch(appStatusProvider).supportsDynamicTheme == false || - (ref.watch(appStatusProvider).supportsDynamicTheme == true && - ref.watch(appStatusProvider).useDynamicTheme == false)) - Padding( - padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16), - child: Scrollbar( - controller: ref.watch(customizationProvider).scrollController, - thumbVisibility: Platform.isMacOS || Platform.isLinux || Platform.isWindows, - interactive: Platform.isMacOS || Platform.isLinux || Platform.isWindows, - thickness: Platform.isMacOS || Platform.isLinux || Platform.isWindows ? 8 : 0, - child: Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: MediaQuery.of(context).size.width, - height: 70, - child: ListView.builder( - controller: ref.watch(customizationProvider).scrollController, - scrollDirection: Axis.horizontal, - itemCount: colors.length, - padding: const EdgeInsets.all(0), - itemBuilder: (context, index) { - if (index == 0) { - return Row( - children: [ - ColorItem( - index: index, - total: colors.length, - color: colors[index], - numericValue: index, - selectedValue: ref.watch(appStatusProvider).selectedColor, - onChanged: ref.read(appStatusProvider.notifier).setSelectedColor, - ), - Container( - margin: const EdgeInsets.symmetric(horizontal: 10), - width: 1, - height: 60, - decoration: BoxDecoration( - color: Colors.grey, - borderRadius: BorderRadius.circular(1), - ), - ), - ], - ); - } else { - return ColorItem( - index: index, - total: colors.length, - color: colors[index], - numericValue: index, - selectedValue: ref.watch(appStatusProvider).selectedColor, - onChanged: ref.read(appStatusProvider.notifier).setSelectedColor, - ); - } - }, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Text( - colorTranslation(ref.watch(appStatusProvider).selectedColor), - style: TextStyle(color: Theme.of(context).listTileTheme.iconColor, fontSize: 16), - ), - ), - ], - ), - ), - ), - ), - ], - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/settings/ui/customization/theme_mode_button.dart b/lib/screens/settings/ui/customization/theme_mode_button.dart deleted file mode 100644 index eb40bce..0000000 --- a/lib/screens/settings/ui/customization/theme_mode_button.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:flutter/material.dart'; - -class ThemeModeButton extends StatelessWidget { - final IconData icon; - final int value; - final int selected; - final String label; - final void Function(int) onChanged; - final bool? disabled; - - const ThemeModeButton({ - super.key, - required this.icon, - required this.value, - required this.selected, - required this.label, - required this.onChanged, - this.disabled, - }); - - @override - Widget build(BuildContext context) { - final Color greyBackgroundColor = Theme.of(context).brightness == Brightness.light - ? const Color.fromRGBO(200, 200, 200, 1) - : const Color.fromRGBO(50, 50, 50, 1); - final Color greyIconColor = Theme.of(context).brightness == Brightness.light - ? const Color.fromRGBO(130, 130, 130, 1) - : const Color.fromRGBO(100, 100, 100, 1); - - return ElevatedButton( - onPressed: disabled == null || disabled == false ? () => onChanged(value) : null, - style: ButtonStyle( - elevation: WidgetStateProperty.all(0), - shape: WidgetStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30), - ), - ), - backgroundColor: WidgetStateProperty.all( - value == selected - ? disabled == null || disabled == false - ? Theme.of(context).colorScheme.primary - : greyBackgroundColor - : disabled == null || disabled == false - ? Theme.of(context).colorScheme.surfaceContainerHighest - : greyBackgroundColor, - ), - ), - child: AnimatedContainer( - width: 118, - height: 150, - curve: Curves.easeInOut, - duration: const Duration(milliseconds: 200), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Icon( - icon, - color: value == selected - ? disabled == null || disabled == false - ? Theme.of(context).colorScheme.primary.computeLuminance() > 0.5 - ? Colors.black - : Colors.white - : greyIconColor - : disabled == null || disabled == false - ? Theme.of(context).colorScheme.primary - : greyIconColor, - size: 30, - ), - Text( - label, - style: TextStyle( - color: value == selected - ? disabled == null || disabled == false - ? Theme.of(context).colorScheme.primary.computeLuminance() > 0.5 - ? Colors.black - : Colors.white - : greyIconColor - : disabled == null || disabled == false - ? Theme.of(context).colorScheme.primary - : greyIconColor, - fontSize: 18, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/screens/settings/ui/default_tags/default_tags.dart b/lib/screens/settings/ui/default_tags/default_tags.dart deleted file mode 100644 index 6c3e15a..0000000 --- a/lib/screens/settings/ui/default_tags/default_tags.dart +++ /dev/null @@ -1,126 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; - -class DefaultTagsScreen extends ConsumerStatefulWidget { - const DefaultTagsScreen({super.key}); - - @override - DefaultTagsScreenState createState() => DefaultTagsScreenState(); -} - -class DefaultTagsScreenState extends ConsumerState { - final _newTagController = TextEditingController(); - bool _addEnabled = false; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(t.settings.generalSettings.defaultTags.defaultTags), - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - if (ref.watch(appStatusProvider).defaultTags.isNotEmpty) - ...ref.watch(appStatusProvider).defaultTags.map( - (tag) => ListTile( - title: Text(tag), - trailing: IconButton( - onPressed: () => ref.read(appStatusProvider.notifier).removeDefaultTag(tag), - icon: const Icon(Icons.delete_rounded), - tooltip: t.settings.generalSettings.defaultTags.removeThisTag, - ), - ), - ), - if (ref.watch(appStatusProvider).defaultTags.isEmpty) - Padding( - padding: const EdgeInsets.all(16), - child: Center( - child: Text( - t.settings.generalSettings.defaultTags.noDefaultTags, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ), - ), - const Divider(), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), - child: Row( - children: [ - Expanded( - child: TextFormField( - controller: _newTagController, - onChanged: (v) => setState(() => v != "" ? _addEnabled = true : _addEnabled = false), - autocorrect: false, - textCapitalization: TextCapitalization.none, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.sell_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - labelText: t.settings.generalSettings.defaultTags.newTag, - ), - onFieldSubmitted: (value) { - ref.read(appStatusProvider.notifier).addDefaultTag(value); - setState(() { - _newTagController.text = ""; - _addEnabled = false; - }); - }, - ), - ), - const SizedBox(width: 16), - IconButton( - onPressed: _addEnabled - ? () { - ref.read(appStatusProvider.notifier).addDefaultTag(_newTagController.text); - setState(() { - _newTagController.text = ""; - _addEnabled = false; - }); - } - : null, - icon: const Icon(Icons.add_rounded), - tooltip: t.settings.generalSettings.defaultTags.addTag, - ), - const SizedBox(width: 8), - ], - ), - ), - ], - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/settings/ui/general_settings/browser_mode_selection_modal.dart b/lib/screens/settings/ui/general_settings/browser_mode_selection_modal.dart deleted file mode 100644 index a8e2aba..0000000 --- a/lib/screens/settings/ui/general_settings/browser_mode_selection_modal.dart +++ /dev/null @@ -1,88 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:linkdy/constants/enums.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; - -class BrowserModeSelectionModal extends ConsumerWidget { - const BrowserModeSelectionModal({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), - ), - child: SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.only(top: 24, left: 24, right: 24, bottom: 8), - child: Column( - children: [ - Icon( - Icons.public_rounded, - color: Theme.of(context).colorScheme.secondary, - size: 24, - ), - const SizedBox(height: 16), - Text( - t.settings.generalSettings.openLinksWith, - style: const TextStyle( - fontSize: 24, - ), - ), - ], - ), - ), - RadioListTile( - value: OpenLinksBrowser.integrated, - groupValue: ref.watch(appStatusProvider).openLinksBrowser, - onChanged: ref.read(appStatusProvider.notifier).updateSelectedBrowser, - title: Text(t.settings.generalSettings.internalBrowser), - ), - RadioListTile( - value: OpenLinksBrowser.browserCustomTab, - groupValue: ref.watch(appStatusProvider).openLinksBrowser, - onChanged: ref.read(appStatusProvider.notifier).updateSelectedBrowser, - title: Text(t.settings.generalSettings.browserCustomTab), - ), - RadioListTile( - value: OpenLinksBrowser.systemBrowser, - groupValue: ref.watch(appStatusProvider).openLinksBrowser, - onChanged: ref.read(appStatusProvider.notifier).updateSelectedBrowser, - title: Text(t.settings.generalSettings.systemBrowser), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(t.generic.close), - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/screens/settings/ui/general_settings/disconnect_modal.dart b/lib/screens/settings/ui/general_settings/disconnect_modal.dart deleted file mode 100644 index 690ee95..0000000 --- a/lib/screens/settings/ui/general_settings/disconnect_modal.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -class DisconnectModal extends ConsumerWidget { - const DisconnectModal({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return AlertDialog( - title: Text(t.settings.generalSettings.disconnectModal.title), - content: Text(t.settings.generalSettings.disconnectModal.description), - actions: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(t.generic.cancel), - ), - const SizedBox(width: 8), - TextButton( - onPressed: () { - Navigator.pop(context); - ref.read(apiClientProvider.notifier).disconnectApiClient(); - }, - child: Text(t.generic.confirm), - ), - ], - ), - ], - ); - } -} diff --git a/lib/screens/settings/ui/general_settings/general_settings.dart b/lib/screens/settings/ui/general_settings/general_settings.dart deleted file mode 100644 index b71d3a8..0000000 --- a/lib/screens/settings/ui/general_settings/general_settings.dart +++ /dev/null @@ -1,125 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/settings/ui/general_settings/browser_mode_selection_modal.dart'; -import 'package:linkdy/screens/settings/ui/general_settings/disconnect_modal.dart'; -import 'package:linkdy/widgets/section_label.dart'; - -import 'package:linkdy/router/paths.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/constants/enums.dart'; - -class GeneralSettings extends ConsumerWidget { - const GeneralSettings({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - void openBrowserSelectionSheet() { - showModalBottomSheet( - context: context, - builder: (context) => const BrowserModeSelectionModal(), - ); - } - - String browserLabel() { - switch (ref.watch(appStatusProvider).openLinksBrowser) { - case OpenLinksBrowser.integrated: - return t.settings.generalSettings.internalBrowser; - case OpenLinksBrowser.browserCustomTab: - return t.settings.generalSettings.browserCustomTab; - case OpenLinksBrowser.systemBrowser: - return t.settings.generalSettings.systemBrowser; - } - } - - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(t.settings.generalSettings.generalSettings), - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - SectionLabel(label: t.settings.generalSettings.bookmarks), - SwitchListTile( - title: Text(t.settings.generalSettings.showFavicon), - subtitle: Text(t.settings.generalSettings.showFaviconDescription), - value: ref.watch(appStatusProvider).showFavicon, - onChanged: ref.read(appStatusProvider.notifier).setShowFavicon, - ), - ListTile( - title: Text(t.settings.generalSettings.openLinksWith), - subtitle: Text(browserLabel()), - onTap: openBrowserSelectionSheet, - ), - SwitchListTile( - title: Text(t.settings.generalSettings.enableSlideOptions), - subtitle: Text(t.settings.generalSettings.enableSlideOptionsDescription), - value: ref.watch(appStatusProvider).enableSlideOptions, - onChanged: ref.read(appStatusProvider.notifier).setEnableSlideOptions, - ), - SectionLabel(label: t.settings.generalSettings.tags), - ListTile( - title: Text(t.settings.generalSettings.defaultTags.defaultTags), - subtitle: Text(t.settings.generalSettings.defaultTags.defaultTagsDescription), - onTap: () => ref.watch(routerProvider).push(RoutesPaths.defaultTags), - ), - SectionLabel(label: t.settings.generalSettings.others), - SwitchListTile( - title: Text(t.settings.generalSettings.setMarkAsUnreadDefault), - subtitle: Text(t.settings.generalSettings.setMarkAsUnreadDefaultDescription), - value: ref.watch(appStatusProvider).markAsUnreadDefault, - onChanged: ref.read(appStatusProvider.notifier).setMarkAsUnreadDefault, - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 16), - child: Divider(), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FilledButton.icon( - onPressed: () => showDialog( - context: context, - builder: (context) => const DisconnectModal(), - ), - icon: const Icon(Icons.clear_rounded), - label: Text( - t.settings.generalSettings.disconnectFromServer, - ), - style: const ButtonStyle( - foregroundColor: WidgetStatePropertyAll(Colors.white), - backgroundColor: WidgetStatePropertyAll(Colors.red), - ), - ), - ], - ), - ], - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/settings/ui/settings.dart b/lib/screens/settings/ui/settings.dart deleted file mode 100644 index 3158c3b..0000000 --- a/lib/screens/settings/ui/settings.dart +++ /dev/null @@ -1,202 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/settings/ui/customization/customization.dart'; -import 'package:linkdy/screens/settings/provider/settings.provider.dart'; -import 'package:linkdy/screens/settings/ui/general_settings/general_settings.dart'; -import 'package:linkdy/widgets/section_label.dart'; -import 'package:linkdy/widgets/custom_list_tile.dart'; -import 'package:linkdy/widgets/custom_settings_tile.dart'; - -import 'package:linkdy/providers/app_info.provider.dart'; -import 'package:linkdy/utils/open_url.dart'; -import 'package:linkdy/constants/strings.dart'; -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/urls.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class SettingsScreen extends ConsumerWidget { - const SettingsScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return LayoutBuilder( - builder: (context, constraints) { - if (constraints.maxWidth > Sizes.tabletBreakpoint) { - return Row( - children: [ - const Expanded(flex: 1, child: _List(tabletView: true)), - Expanded(flex: 2, child: Material(child: const _DetailPanel())), - ], - ); - } else { - return const _List(tabletView: false); - } - }, - ); - } -} - -class _List extends ConsumerWidget { - final bool tabletView; - - const _List({ - required this.tabletView, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(t.settings.settings), - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverList.list( - children: [ - SectionLabel(label: t.settings.appSettings), - _SettingsTile( - icon: Icons.palette_rounded, - title: t.settings.customization.customization, - subtitle: t.settings.customization.customizationDescription, - thisItem: 0, - twoColumns: tabletView, - screenToNavigate: const Customization(), - ), - _SettingsTile( - icon: Icons.settings_rounded, - title: t.settings.generalSettings.generalSettings, - subtitle: t.settings.generalSettings.generalSettingsDescription, - thisItem: 1, - screenToNavigate: const GeneralSettings(), - twoColumns: tabletView, - ), - SectionLabel(label: t.settings.aboutApp), - CustomListTile( - title: t.settings.linkdingRepository, - subtitle: t.settings.linkdingRepositoryDescription, - trailing: Icon( - Icons.open_in_new_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - onTap: () => openUrlCustomTab(Urls.linkdingRepo), - ), - CustomListTile( - title: t.settings.moreInfoApp, - subtitle: t.settings.moreInfoAppDescription, - trailing: Icon( - Icons.open_in_new_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - onTap: () => openUrlCustomTab(Urls.appDetailsPage), - ), - CustomListTile( - title: t.settings.moreApps, - subtitle: t.settings.moreAppsDescription, - trailing: Icon( - Icons.open_in_new_rounded, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - onTap: () => openUrlCustomTab(Urls.appsWebsite), - ), - CustomListTile( - title: t.settings.appVersion, - subtitle: ref.watch(appInfoProvider).version, - ), - CustomListTile( - title: t.settings.createdBy, - subtitle: Strings.createdBy, - ), - ], - ), - ], - ), - ), - ), - ), - ); - } -} - -class _SettingsTile extends ConsumerWidget { - final String title; - final String subtitle; - final IconData icon; - final Widget screenToNavigate; - final int thisItem; - final bool twoColumns; - - const _SettingsTile({ - required this.title, - required this.subtitle, - required this.icon, - required this.screenToNavigate, - required this.thisItem, - required this.twoColumns, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - if (twoColumns) { - return CustomSettingsTile( - title: title, - subtitle: subtitle, - icon: icon, - thisItem: thisItem, - selectedItem: ref.watch(settingsProvider).selectedScreen, - onTap: () { - ref.read(settingsProvider.notifier).setSelectedScreen(thisItem); - }, - ); - } else { - return CustomListTile( - title: title, - subtitle: subtitle, - icon: icon, - onTap: () { - Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (context) => screenToNavigate)); - }, - ); - } - } -} - -class _DetailPanel extends ConsumerWidget { - const _DetailPanel(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final selectedScreen = ref.watch(settingsProvider).selectedScreen; - - switch (selectedScreen) { - case 0: - return const Customization(); - case 1: - return const GeneralSettings(); - default: - return Center( - child: Text( - t.settings.selectAnOption, - style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), - ), - ); - } - } -} diff --git a/lib/screens/tags/models/add_tag.modal.dart b/lib/screens/tags/models/add_tag.modal.dart deleted file mode 100644 index b07290d..0000000 --- a/lib/screens/tags/models/add_tag.modal.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flutter/material.dart'; - -class AddTagModel { - final TextEditingController nameController; - - const AddTagModel({ - required this.nameController, - }); -} diff --git a/lib/screens/tags/models/tags.model.dart b/lib/screens/tags/models/tags.model.dart deleted file mode 100644 index 9fd8bfe..0000000 --- a/lib/screens/tags/models/tags.model.dart +++ /dev/null @@ -1,9 +0,0 @@ -class TagsModel { - int currentPage; - int limit; - - TagsModel({ - this.currentPage = 0, - this.limit = 100, - }); -} diff --git a/lib/screens/tags/provider/add_tag.provider.dart b/lib/screens/tags/provider/add_tag.provider.dart deleted file mode 100644 index 621cc6a..0000000 --- a/lib/screens/tags/provider/add_tag.provider.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/screens/tags/ui/add_tag_error_modal.dart'; -import 'package:linkdy/screens/tags/provider/tags.provider.dart'; -import 'package:linkdy/screens/tags/models/add_tag.modal.dart'; - -import 'package:linkdy/router/routes.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/utils/process_modal.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -part 'add_tag.provider.g.dart'; - -@riverpod -class AddTag extends _$AddTag { - @override - AddTagModel build() { - return AddTagModel( - nameController: TextEditingController(), - ); - } - - void notifyOnWrite() { - ref.notifyListeners(); - } - - void onAddTag() async { - final processModal = ProcessModal(); - processModal.open(t.tags.createTag.creatingTag); - - final result = await ref.watch(apiClientProvider)!.postTag(state.nameController.text); - - processModal.close(); - if (result.successful == true) { - ref.invalidate(tagsRequestProvider); - ref.watch(routerProvider).pop(); - } else { - if (rootNavigatorKey.currentContext == null) return; - showDialog( - context: rootNavigatorKey.currentContext!, - builder: (context) => const AddTagErrorModal(), - ); - } - } -} diff --git a/lib/screens/tags/provider/add_tag.provider.g.dart b/lib/screens/tags/provider/add_tag.provider.g.dart deleted file mode 100644 index 1614e1e..0000000 --- a/lib/screens/tags/provider/add_tag.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'add_tag.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$addTagHash() => r'8157bc7911ae64627adabbe1528f519a4b1cb913'; - -/// See also [AddTag]. -@ProviderFor(AddTag) -final addTagProvider = - AutoDisposeNotifierProvider.internal( - AddTag.new, - name: r'addTagProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$addTagHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$AddTag = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/tags/provider/tags.provider.dart b/lib/screens/tags/provider/tags.provider.dart deleted file mode 100644 index cd69331..0000000 --- a/lib/screens/tags/provider/tags.provider.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:linkdy/screens/tags/models/tags.model.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -import 'package:linkdy/models/data/tags.dart'; -import 'package:linkdy/models/api_response.dart'; -import 'package:linkdy/providers/api_client.provider.dart'; - -part 'tags.provider.g.dart'; - -@riverpod -FutureOr> tagsRequest(TagsRequestRef ref) async { - final result = await ref.watch(apiClientProvider)!.fetchTags(); - return result; -} - -@riverpod -class Tags extends _$Tags { - @override - TagsModel build() { - return TagsModel(); - } - - void setCurrentPage(int page) { - state.currentPage = page; - } - - void setLimit(int limit) { - state.limit = limit; - } -} diff --git a/lib/screens/tags/provider/tags.provider.g.dart b/lib/screens/tags/provider/tags.provider.g.dart deleted file mode 100644 index 2f7eed9..0000000 --- a/lib/screens/tags/provider/tags.provider.g.dart +++ /dev/null @@ -1,40 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'tags.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$tagsRequestHash() => r'52b3c212ed070b39718aef1010c44fbb7120ef51'; - -/// See also [tagsRequest]. -@ProviderFor(tagsRequest) -final tagsRequestProvider = - AutoDisposeFutureProvider>.internal( - tagsRequest, - name: r'tagsRequestProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$tagsRequestHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef TagsRequestRef - = AutoDisposeFutureProviderRef>; -String _$tagsHash() => r'6e26b566459377a3a6bc0f1884b9a05855151d3f'; - -/// See also [Tags]. -@ProviderFor(Tags) -final tagsProvider = AutoDisposeNotifierProvider.internal( - Tags.new, - name: r'tagsProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$tagsHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$Tags = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/tags/ui/add_tag_error_modal.dart b/lib/screens/tags/ui/add_tag_error_modal.dart deleted file mode 100644 index 72aa7ca..0000000 --- a/lib/screens/tags/ui/add_tag_error_modal.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class AddTagErrorModal extends StatelessWidget { - const AddTagErrorModal({super.key}); - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Text(t.generic.error), - content: Text(t.tags.createTag.errorCreatingTag), - actions: [ - Row( - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(t.generic.close), - ), - ], - ), - ], - ); - } -} diff --git a/lib/screens/tags/ui/add_tag_modal.dart b/lib/screens/tags/ui/add_tag_modal.dart deleted file mode 100644 index cbefb7c..0000000 --- a/lib/screens/tags/ui/add_tag_modal.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/tags/provider/add_tag.provider.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; - -class AddTagModal extends ConsumerWidget { - const AddTagModal({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final provider = ref.watch(addTagProvider); - - return Padding( - padding: MediaQuery.of(context).viewInsets, - child: Container( - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(28), - topRight: Radius.circular(28), - ), - color: Theme.of(context).dialogBackgroundColor, - ), - child: SafeArea( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.add_rounded, - color: Theme.of(context).colorScheme.secondary, - size: 24, - ), - const SizedBox(height: 16), - Text( - t.tags.createTag.createTag, - style: const TextStyle( - fontSize: 24, - ), - ), - const SizedBox(height: 24), - TextFormField( - controller: provider.nameController, - onChanged: (_) => ref.read(addTagProvider.notifier).notifyOnWrite(), - autocorrect: false, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.label_rounded), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), - labelText: t.tags.createTag.name, - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(top: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text(t.generic.cancel), - ), - const SizedBox(width: 8), - TextButton( - onPressed: provider.nameController.text != "" - ? () => ref.read(addTagProvider.notifier).onAddTag() - : null, - child: Text(t.generic.confirm), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/screens/tags/ui/tags.dart b/lib/screens/tags/ui/tags.dart deleted file mode 100644 index e90da28..0000000 --- a/lib/screens/tags/ui/tags.dart +++ /dev/null @@ -1,147 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -import 'package:linkdy/screens/tags/provider/tags.provider.dart'; -import 'package:linkdy/screens/tags/ui/add_tag_modal.dart'; -import 'package:linkdy/widgets/error_screen.dart'; -import 'package:linkdy/widgets/no_data_screen.dart'; - -import 'package:linkdy/utils/date_to_string.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/providers/router.provider.dart'; -import 'package:linkdy/router/names.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class TagsScreen extends ConsumerWidget { - const TagsScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final tags = ref.watch(tagsRequestProvider); - - void openAddModal() { - showModalBottomSheet( - context: context, - useRootNavigator: true, - isScrollControlled: true, - builder: (context) => const AddTagModal(), - ); - } - - return ScaffoldMessenger( - key: ScaffoldMessengerKeys.tags, - child: Scaffold( - body: NestedScrollView( - headerSliverBuilder: (context, innerBoxIsScrolled) => [ - SliverOverlapAbsorber( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverAppBar.large( - pinned: true, - floating: true, - centerTitle: false, - forceElevated: innerBoxIsScrolled, - title: Text(t.tags.tags), - ), - ), - ], - body: SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (context) => RefreshIndicator( - displacement: 120, - onRefresh: () => ref.refresh(tagsRequestProvider.future), - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (tags.isLoading && !tags.isRefreshing) - const SliverFillRemaining( - child: Center(child: CircularProgressIndicator()), - ), - if (tags.value != null && tags.value!.successful == false) - SliverFillRemaining( - child: ErrorScreen( - error: t.bookmarks.cannotLoadBookmarks, - ), - ), - if (tags.value != null && tags.value!.successful == true && tags.value!.content!.results!.isEmpty) - SliverFillRemaining( - child: NoDataScreen( - message: t.bookmarks.noBookmarksAdded, - ), - ), - if (tags.value != null && - tags.value!.successful == true && - tags.value!.content!.results!.isNotEmpty) - SliverList.builder( - itemCount: tags.value!.content!.results!.length + 1, - itemBuilder: (context, index) { - // index == bookmarks.value!.content!.results!.length -> itemCount + 1 - if (index == tags.value!.content!.results!.length) { - // Bottom gap for FAB - return const SizedBox(height: 80); - } - final tag = tags.value?.content?.results?[index]; - return InkWell( - onTap: () => ref.watch(routerProvider).pushNamed( - RoutesNames.tagBookmarks, - extra: tag, - pathParameters: {'id': tag.id!.toString()}, - ), - child: Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon( - Icons.label_rounded, - size: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.7), - ), - const SizedBox(width: 8), - Flexible( - child: Text( - tag!.name!, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - t.tags.created(created: dateToString(tag.dateAdded!)), - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ), - ); - }, - ), - ], - ), - ), - ), - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: openAddModal, - child: const Icon(Icons.add_rounded), - ), - ), - ); - } -} diff --git a/lib/screens/webview/model/webview.model.dart b/lib/screens/webview/model/webview.model.dart deleted file mode 100644 index b50e06e..0000000 --- a/lib/screens/webview/model/webview.model.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:webview_flutter/webview_flutter.dart'; - -class WebViewModel { - final WebViewController webViewController; - int loadProgress; - bool canGoBack; - bool canGoForward; - - WebViewModel({ - required this.webViewController, - this.loadProgress = 0, - this.canGoBack = false, - this.canGoForward = false, - }); -} diff --git a/lib/screens/webview/provider/webview.provider.dart b/lib/screens/webview/provider/webview.provider.dart deleted file mode 100644 index aa37d84..0000000 --- a/lib/screens/webview/provider/webview.provider.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:webview_flutter/webview_flutter.dart'; - -import 'package:linkdy/screens/bookmarks/provider/bookmarks.provider.dart'; -import 'package:linkdy/screens/bookmarks/provider/search_bookmarks.provider.dart'; -import 'package:linkdy/screens/filtered_bookmarks/provider/filtered_bookmarks.provider.dart'; -import 'package:linkdy/screens/webview/model/webview.model.dart'; - -part 'webview.provider.g.dart'; - -@riverpod -class WebView extends _$WebView { - @override - WebViewModel build() { - return WebViewModel( - webViewController: WebViewController() - ..setNavigationDelegate( - NavigationDelegate( - onProgress: (progress) { - state.loadProgress = progress; - ref.notifyListeners(); - }, - onUrlChange: (change) { - state.webViewController.canGoBack().then((value) { - state.canGoBack = value; - ref.notifyListeners(); - }); - state.webViewController.canGoForward().then((value) { - state.canGoForward = value; - ref.notifyListeners(); - }); - }, - ), - ), - ); - } - - void setLoadProgress(int progress) { - state.loadProgress = progress; - ref.notifyListeners(); - } - - void setCanGoBack(bool value) { - state.canGoBack = value; - ref.notifyListeners(); - } - - void setCanGoForward(bool value) { - state.canGoForward = value; - ref.notifyListeners(); - } - - void loadNewUrl(String url) { - ref.invalidateSelf(); - state.webViewController.loadRequest(Uri.parse(url)); - } - - void closeWebviewSplit() { - ref.read(bookmarksProvider.notifier).clearSelectedBookmark(); - ref.read(searchBookmarksProvider.notifier).clearSelectedBookmark(); - ref.read(filteredBookmarksProvider.notifier).clearSelectedBookmark(); - ref.notifyListeners(); - } -} diff --git a/lib/screens/webview/provider/webview.provider.g.dart b/lib/screens/webview/provider/webview.provider.g.dart deleted file mode 100644 index 7980799..0000000 --- a/lib/screens/webview/provider/webview.provider.g.dart +++ /dev/null @@ -1,25 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'webview.provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -String _$webViewHash() => r'777a5c7245e32f3334c676aa2bf18d953be1233a'; - -/// See also [WebView]. -@ProviderFor(WebView) -final webViewProvider = - AutoDisposeNotifierProvider.internal( - WebView.new, - name: r'webViewProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$webViewHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$WebView = AutoDisposeNotifier; -// ignore_for_file: type=lint -// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member diff --git a/lib/screens/webview/ui/invalid_bookmark.dart b/lib/screens/webview/ui/invalid_bookmark.dart deleted file mode 100644 index a8db473..0000000 --- a/lib/screens/webview/ui/invalid_bookmark.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -import 'package:linkdy/widgets/error_screen.dart'; - -class InvalidBookmarkScreen extends StatelessWidget { - const InvalidBookmarkScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(), - body: Center( - child: ErrorScreen(error: t.webview.invalidBookmarkData), - ), - ); - } -} diff --git a/lib/screens/webview/ui/webview.dart b/lib/screens/webview/ui/webview.dart deleted file mode 100644 index 8cc959f..0000000 --- a/lib/screens/webview/ui/webview.dart +++ /dev/null @@ -1,167 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:webview_flutter/webview_flutter.dart'; -import 'package:share_plus/share_plus.dart'; - -import 'package:linkdy/screens/webview/provider/webview.provider.dart'; - -import 'package:linkdy/config/sizes.dart'; -import 'package:linkdy/constants/global_keys.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/utils/copy_clipboard.dart'; -import 'package:linkdy/utils/open_url.dart'; - -class WebViewScreen extends HookConsumerWidget { - final Bookmark bookmark; - - const WebViewScreen({ - super.key, - required this.bookmark, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - useEffect( - () { - ref.read(webViewProvider.notifier).loadNewUrl(bookmark.url!); - return null; - }, - [bookmark], - ); - - final width = MediaQuery.of(context).size.width; - - return Scaffold( - appBar: AppBar( - elevation: 3, - leading: width > Sizes.tabletBreakpoint - ? CloseButton( - onPressed: () { - ref.read(webViewProvider.notifier).closeWebviewSplit(); - Navigator.pop(context); - }, - ) - : null, - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - bookmark.title ?? bookmark.websiteTitle ?? "Website", - style: const TextStyle(fontSize: 14), - ), - const SizedBox(height: 4), - Text( - bookmark.url ?? "", - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - bottom: PreferredSize( - preferredSize: const Size(double.maxFinite, 0), - child: ref.watch(webViewProvider).loadProgress < 100 - ? const LinearProgressIndicator() - : const SizedBox( - height: 4, - ), - ), - ), - body: SafeArea( - child: Column( - children: [ - Expanded( - child: WebViewWidget( - controller: ref.watch(webViewProvider).webViewController, - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - IconButton( - onPressed: ref.watch(webViewProvider).canGoBack == true - ? () => ref.watch(webViewProvider).webViewController.goBack() - : null, - icon: const Icon(Icons.arrow_back_rounded), - tooltip: t.webview.goForward, - ), - const SizedBox(width: 8), - IconButton( - onPressed: ref.watch(webViewProvider).canGoForward == true - ? () => ref.watch(webViewProvider).webViewController.goForward() - : null, - icon: const Icon(Icons.arrow_forward_rounded), - tooltip: t.webview.goForward, - ), - const SizedBox(width: 16), - IconButton( - onPressed: () => ref.watch(webViewProvider).webViewController.reload(), - icon: const Icon(Icons.refresh_rounded), - tooltip: t.webview.reload, - ), - ], - ), - Builder( - builder: (ctx) { - return PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - onTap: () { - final box = ctx.findRenderObject() as RenderBox?; - Share.share( - bookmark.url!, - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, - ); - }, - child: Row( - children: [ - const Icon(Icons.share_rounded), - const SizedBox(width: 12), - Flexible(child: Text(t.webview.share)), - ], - ), - ), - PopupMenuItem( - onTap: () => copyToClipboard( - key: ScaffoldMessengerKeys.root, - value: bookmark.url!, - successMessage: t.webview.linkCopiedClipboard, - ), - child: Row( - children: [ - const Icon(Icons.copy_rounded), - const SizedBox(width: 12), - Flexible(child: Text(t.webview.copyLinkClipboard)), - ], - ), - ), - PopupMenuItem( - onTap: () => openUrlCustomTab(bookmark.url!), - child: Row( - children: [ - const Icon(Icons.open_in_browser_rounded), - const SizedBox(width: 12), - Flexible(child: Text(t.webview.openInSystemBrowser)), - ], - ), - ), - ], - ); - }, - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/services/api_client.dart b/lib/services/api_client.dart deleted file mode 100644 index a7a5d87..0000000 --- a/lib/services/api_client.dart +++ /dev/null @@ -1,343 +0,0 @@ -import 'package:dio/dio.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; - -import 'package:linkdy/constants/enums.dart'; -import 'package:linkdy/models/api_response.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/models/data/check_bookmark.dart'; -import 'package:linkdy/models/data/patch_bookmark_data.dart'; -import 'package:linkdy/models/data/set_bookmark_data.dart'; -import 'package:linkdy/models/data/tags.dart'; -import 'package:linkdy/models/server_instance.dart'; - -Future testServerReachability(String url) async { - try { - await Dio(BaseOptions(connectTimeout: const Duration(seconds: 5))).get("$url/api/"); - return true; - } on DioException catch (e) { - if (e.response?.statusCode != null) { - return true; - } - return false; - } catch (e) { - return false; - } -} - -class ApiClientService { - final ServerInstance serverInstance; - final Dio dioInstance; - - const ApiClientService({ - required this.serverInstance, - required this.dioInstance, - }); - - Future checkConnectionInstance() async { - try { - await dioInstance.get("/bookmarks/?limit=1"); - return AuthResult.success; - } on DioException catch (e) { - if (e.response != null && e.response!.statusCode == 401 || e.response!.statusCode == 403) { - return AuthResult.invalidToken; - } - return AuthResult.other; - } catch (e) { - return AuthResult.other; - } - } - - Future> fetchBookmarks({ - String? q, - int? limit, - int? offset, - ReadStatus? unread, - String? sort, - }) async { - try { - final response = await dioInstance.get( - "/bookmarks/", - queryParameters: { - "q": q, - "limit": limit, - "offset": offset, - "unread": unread == ReadStatus.unread - ? "yes" - : unread == ReadStatus.read - ? "no" - : null, - "sort": sort, - }, - ); - if (response.statusCode == null || response.statusCode! >= 400) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: BookmarksResponse.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> fetchArchivedBookmarks({String? q, int? limit, int? offset}) async { - try { - final response = await dioInstance.get( - "/bookmarks/archived/", - queryParameters: { - "q": q, - "limit": limit, - "offset": offset, - }, - ); - if (response.statusCode != 200) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: BookmarksResponse.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> fetchSharedBookmarks({String? q, int? limit, int? offset}) async { - try { - final response = await dioInstance.get( - "/bookmarks/shared/", - queryParameters: { - "q": q, - "limit": limit, - "offset": offset, - }, - ); - if (response.statusCode != 200) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: BookmarksResponse.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> fetchCheckAddBookmark({required String url}) async { - try { - final response = await dioInstance.get( - "/bookmarks/check", - queryParameters: { - "url": url, - }, - ); - if (response.statusCode != 200) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: CheckBookmark.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> postBookmark(SetBookmarkData bookmark) async { - try { - final response = await dioInstance.post( - "/bookmarks/", - data: FormData.fromMap(bookmark.toJson()), - ); - if (response.statusCode == null || response.statusCode! >= 400) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: Bookmark.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> fetchTags({String? q, int? limit, int? offset}) async { - try { - final response = await dioInstance.get( - "/tags/", - queryParameters: { - "q": q, - "limit": limit, - "offset": offset, - }, - ); - if (response.statusCode != 200) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: TagsResponse.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> postTag(String name) async { - try { - final response = await dioInstance.post( - "/tags/", - data: FormData.fromMap({"name": name}), - ); - return ApiResponse( - successful: true, - content: Tag.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> fetchTagById(String tagId) async { - try { - final response = await dioInstance.get("/tags/$tagId/"); - if (response.statusCode != 200) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: Tag.fromJson(response.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> postDeleteBookmark(int bookmarkId) async { - try { - await dioInstance.delete("/bookmarks/$bookmarkId/"); - return const ApiResponse(successful: true); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> putUpdateBookmark(int bookmarkId, SetBookmarkData bookmark) async { - try { - final result = await dioInstance.put( - "/bookmarks/$bookmarkId/", - data: FormData.fromMap(bookmark.toJson()), - ); - if (result.statusCode == null || result.statusCode! >= 400) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: Bookmark.fromJson(result.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> postArchiveBookmark(int bookmarkId) async { - try { - await dioInstance.post("/bookmarks/$bookmarkId/archive/"); - return const ApiResponse(successful: true); - } on DioException { - return const ApiResponse(successful: false); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } - } - - Future> postUnrchiveBookmark(int bookmarkId) async { - try { - await dioInstance.post("/bookmarks/$bookmarkId/unarchive/"); - return const ApiResponse(successful: true); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } - - Future> patchUpdateBookmark(int bookmarkId, PatchBookmarkData bookmark) async { - try { - final result = await dioInstance.patch( - "/bookmarks/$bookmarkId/", - data: FormData.fromMap(bookmark.toJson()), - ); - if (result.statusCode != 200) { - return const ApiResponse(successful: false); - } - return ApiResponse( - successful: true, - content: Bookmark.fromJson(result.data), - ); - } on DioException { - return const ApiResponse(successful: false); - } on FormatException catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - return const ApiResponse(successful: false); - } catch (_) { - return const ApiResponse(successful: false); - } - } -} diff --git a/lib/utils/api_base_url.dart b/lib/utils/api_base_url.dart deleted file mode 100644 index ec7853f..0000000 --- a/lib/utils/api_base_url.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:linkdy/models/server_instance.dart'; - -String apiBaseUrl(ServerInstance server) { - return "${server.method}://${server.ipDomain}${server.port != null ? ':${server.port}' : ""}${server.path ?? ''}/api"; -} diff --git a/lib/utils/color_translation.dart b/lib/utils/color_translation.dart deleted file mode 100644 index 0b59177..0000000 --- a/lib/utils/color_translation.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:linkdy/i18n/strings.g.dart'; - -String colorTranslation(int index) { - // This indexes has to be in sync with colors array at constants/colors.dart - List translations = [ - "Linkding", - t.colors.red, - t.colors.green, - t.colors.blue, - t.colors.yellow, - t.colors.orange, - t.colors.brown, - t.colors.cyan, - t.colors.purple, - t.colors.pink, - t.colors.deepOrange, - t.colors.indigo, - ]; - return translations[index]; -} diff --git a/lib/utils/copy_clipboard.dart b/lib/utils/copy_clipboard.dart deleted file mode 100644 index dac7aac..0000000 --- a/lib/utils/copy_clipboard.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -void copyToClipboard({ - required GlobalKey key, - required String value, - required String successMessage, -}) async { - await Clipboard.setData( - ClipboardData(text: value), - ); - key.currentState!.showSnackBar( - SnackBar( - content: Text(successMessage), - backgroundColor: Colors.green, - ), - ); -} diff --git a/lib/utils/date_to_string.dart b/lib/utils/date_to_string.dart deleted file mode 100644 index 6f2ce7d..0000000 --- a/lib/utils/date_to_string.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:linkdy/i18n/strings.g.dart'; - -String dateToString(DateTime date) { - String addZeros(int value) { - return value.toString().padLeft(2, '0'); - } - - final today = DateTime.now(); - final yesterday = DateTime.now().subtract(const Duration(days: 1)); - - final localDate = date.toLocal(); - - if (localDate.day == today.day && localDate.month == today.month && localDate.year == today.year) { - return t.bookmarks.dates.todayAt(time: "${addZeros(localDate.hour)}:${addZeros(localDate.minute)}"); - } else if (localDate.day == yesterday.day && localDate.month == yesterday.month && localDate.year == yesterday.year) { - return t.bookmarks.dates.yesterdayAt(time: "${addZeros(localDate.hour)}:${addZeros(localDate.minute)}"); - } else { - return "${localDate.day}/${localDate.month}/${localDate.year} - ${addZeros(localDate.hour)}:${addZeros(localDate.minute)}"; - } -} diff --git a/lib/utils/http_overrides.dart b/lib/utils/http_overrides.dart deleted file mode 100644 index b695d8e..0000000 --- a/lib/utils/http_overrides.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'dart:io'; - -class MyHttpOverrides extends HttpOverrides { - @override - HttpClient createHttpClient(SecurityContext? context) { - return super.createHttpClient(context) - ..badCertificateCallback = (X509Certificate cert, String host, int port) => true; - } -} diff --git a/lib/utils/open_url.dart b/lib/utils/open_url.dart deleted file mode 100644 index be8d4ec..0000000 --- a/lib/utils/open_url.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'dart:io'; - -import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as flutter_custom_tabs; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:url_launcher/url_launcher.dart' as url_launcher; - -void openUrlCustomTab(String url) async { - if (Platform.isAndroid || Platform.isIOS) { - try { - await flutter_custom_tabs.launchUrl( - Uri.parse(url), - customTabsOptions: const flutter_custom_tabs.CustomTabsOptions( - shareState: flutter_custom_tabs.CustomTabsShareState.browserDefault, - urlBarHidingEnabled: true, - showTitle: true, - browser: flutter_custom_tabs.CustomTabsBrowserConfiguration(prefersDefaultBrowser: true), - ), - safariVCOptions: const flutter_custom_tabs.SafariViewControllerOptions( - barCollapsingEnabled: true, - dismissButtonStyle: flutter_custom_tabs.SafariViewControllerDismissButtonStyle.close, - ), - ); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - } - } else { - try { - url_launcher.launchUrl(Uri.parse(url)); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - } - } -} - -void openUrlSystemBrowser(String url) async { - if (Platform.isAndroid || Platform.isIOS) { - try { - await flutter_custom_tabs.launchUrl( - Uri.parse(url), - customTabsOptions: null, - safariVCOptions: null, - ); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - } - } else { - try { - url_launcher.launchUrl(Uri.parse(url)); - } catch (e, stackTrace) { - Sentry.captureException(e, stackTrace: stackTrace); - } - } -} diff --git a/lib/utils/process_modal.dart b/lib/utils/process_modal.dart deleted file mode 100644 index 86fe2de..0000000 --- a/lib/utils/process_modal.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:linkdy/widgets/process_dialog.dart'; - -import 'package:linkdy/router/routes.dart'; - -class ProcessModal { - void open(String message) async { - await Future.delayed( - const Duration(seconds: 0), - () => { - showDialog( - context: rootNavigatorKey.currentContext!, - builder: (ctx) { - return ProcessDialog( - message: message, - ); - }, - barrierDismissible: false, - useSafeArea: true, - ), - }, - ); - } - - void close() { - Navigator.pop(rootNavigatorKey.currentContext!); - } -} diff --git a/lib/utils/sentry_handle_error.dart b/lib/utils/sentry_handle_error.dart deleted file mode 100644 index ef0f197..0000000 --- a/lib/utils/sentry_handle_error.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'dart:async'; - -import 'package:sentry_flutter/sentry_flutter.dart'; - -FutureOr sentryHandleError(SentryEvent event, Hint hint) async { - // Remove logs coming from the favicon library - final containsFavicon = event.exceptions - ?.where( - (e) => e.stackTrace?.frames.where((f) => f.fileName?.contains("favicon.dart") ?? false).isNotEmpty ?? false, - ) - .isNotEmpty; - if (containsFavicon == true) { - return null; - } - - return event; -} diff --git a/lib/utils/snackbar.dart b/lib/utils/snackbar.dart deleted file mode 100644 index a0e6a1e..0000000 --- a/lib/utils/snackbar.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/material.dart'; - -void showSnackbar({ - required GlobalKey key, - required String label, - required Color color, - Color? labelColor, -}) { - final snackBar = SnackBar( - content: Text( - label, - style: TextStyle(color: labelColor ?? Colors.white), - ), - backgroundColor: color, - ); - key.currentState?.showSnackBar(snackBar); -} diff --git a/lib/utils/tab_content_list.dart b/lib/utils/tab_content_list.dart deleted file mode 100644 index f70313d..0000000 --- a/lib/utils/tab_content_list.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:linkdy/constants/enums.dart'; - -class CustomTabContentList extends StatelessWidget { - final Widget Function() loadingGenerator; - final int itemsCount; - final Widget Function(int index) contentWidget; - final Widget noData; - final Widget Function() errorGenerator; - final LoadStatus loadStatus; - final Future Function() onRefresh; - final double? refreshIndicatorOffset; - final bool? fabVisible; - final bool? noSliver; - final EdgeInsets? listPadding; - final double? heightFabHidden; - - const CustomTabContentList({ - super.key, - required this.loadingGenerator, - required this.itemsCount, - required this.contentWidget, - required this.noData, - required this.errorGenerator, - required this.loadStatus, - required this.onRefresh, - this.refreshIndicatorOffset, - this.fabVisible, - this.noSliver, - this.listPadding, - this.heightFabHidden, - }); - - @override - Widget build(BuildContext context) { - switch (loadStatus) { - case LoadStatus.loading: - if (noSliver == true) { - return Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: loadingGenerator()); - } else { - return SafeArea( - top: false, - child: Builder( - builder: (BuildContext context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: loadingGenerator()), - ), - ], - ), - ), - ); - } - - case LoadStatus.loaded: - if (noSliver == true) { - if (itemsCount > 0) { - return SafeArea( - child: ListView.builder( - padding: listPadding, - itemCount: itemsCount, - itemBuilder: (context, index) => contentWidget(index), - ), - ); - } else { - return SafeArea( - child: noData, - ); - } - } else { - return SafeArea( - top: false, - bottom: false, - child: Builder( - builder: (BuildContext context) { - return RefreshIndicator( - onRefresh: onRefresh, - edgeOffset: refreshIndicatorOffset ?? 70, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - if (itemsCount > 0) - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) => contentWidget(index), - childCount: itemsCount, - ), - ), - if (itemsCount == 0) - SliverFillRemaining( - child: noData, - ), - ], - ), - ); - }, - ), - ); - } - - case LoadStatus.error: - if (noSliver == true) { - return Padding(padding: const EdgeInsets.only(top: 95, left: 16, right: 16), child: errorGenerator()); - } else { - return SafeArea( - top: false, - child: Builder( - builder: (BuildContext context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - SliverFillRemaining( - child: Padding( - padding: const EdgeInsets.only(top: 95, left: 16, right: 16), - child: errorGenerator(), - ), - ), - ], - ), - ), - ); - } - } - } -} diff --git a/lib/widgets/bookmark_item/bookmark_context_menu.dart b/lib/widgets/bookmark_item/bookmark_context_menu.dart deleted file mode 100644 index 419be0d..0000000 --- a/lib/widgets/bookmark_item/bookmark_context_menu.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:share_plus/share_plus.dart'; - -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class BookmarkContextMenu extends ConsumerWidget { - final Widget child; - final Bookmark bookmark; - final void Function(Bookmark bookmark) onSelect; - final void Function(Bookmark bookmark) onDelete; - final void Function(Bookmark bookmark) onReadUnread; - final void Function(Bookmark bookmark) onArchiveUnarchive; - final void Function(Bookmark bookmark) onEdit; - final void Function(Bookmark bookmark) onShareInternally; - - const BookmarkContextMenu({ - super.key, - required this.bookmark, - required this.child, - required this.onSelect, - required this.onDelete, - required this.onReadUnread, - required this.onArchiveUnarchive, - required this.onEdit, - required this.onShareInternally, - }); - - void _showBottomSheet(BuildContext context) { - showModalBottomSheet( - context: context, - isDismissible: true, - builder: (ctx) => SafeArea( - bottom: true, - top: true, - child: Wrap( - children: [ - Padding( - padding: const EdgeInsets.symmetric(vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 50, - height: 4, - decoration: BoxDecoration( - color: Colors.grey, - borderRadius: BorderRadius.circular(20), - ), - ), - ], - ), - ), - ListTile( - leading: Icon( - bookmark.unread == true ? Icons.mark_email_read_rounded : Icons.mark_as_unread_rounded, - ), - title: Text( - bookmark.unread == true - ? t.bookmarks.bookmarkOptions.markAsRead - : t.bookmarks.bookmarkOptions.markAsUnread, - ), - onTap: () { - Navigator.pop(ctx); - onReadUnread(bookmark); - }, - ), - ListTile( - leading: Icon( - bookmark.isArchived == true ? Icons.unarchive_rounded : Icons.archive_rounded, - ), - title: Text( - bookmark.isArchived == true - ? t.bookmarks.bookmarkOptions.unarchive - : t.bookmarks.bookmarkOptions.archive, - ), - onTap: () { - Navigator.pop(ctx); - onArchiveUnarchive(bookmark); - }, - ), - ExpansionTile( - leading: const Icon(Icons.share_rounded), - title: Text(t.bookmarks.bookmarkOptions.shareOptions), - children: [ - ListTile( - contentPadding: const EdgeInsets.only(left: 44), - leading: const Icon(Icons.input_rounded), - title: Text( - bookmark.shared == true - ? t.bookmarks.bookmarkOptions.unshareInternally - : t.bookmarks.bookmarkOptions.shareInternally, - ), - onTap: () { - Navigator.pop(ctx); - onShareInternally(bookmark); - }, - ), - ListTile( - contentPadding: const EdgeInsets.only(left: 44), - leading: const Icon(Icons.output_rounded), - title: Text(t.bookmarks.bookmarkOptions.shareThirdPartyApp), - onTap: () { - Navigator.pop(ctx); - Share.share(bookmark.url!); - }, - ), - ], - ), - ListTile( - leading: const Icon(Icons.edit_rounded), - title: Text(t.bookmarks.bookmarkOptions.edit), - onTap: () { - Navigator.pop(ctx); - onEdit(bookmark); - }, - ), - ListTile( - leading: Icon( - Icons.delete_rounded, - color: Theme.of(ctx).colorScheme.error, - ), - title: Text( - t.bookmarks.bookmarkOptions.delete, - style: TextStyle(color: Theme.of(ctx).colorScheme.error), - ), - onTap: () { - Navigator.pop(ctx); - onDelete(bookmark); - }, - ), - ], - ), - ), - ); - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - return GestureDetector( - onLongPress: () => _showBottomSheet(context), - child: child, - ); - } -} diff --git a/lib/widgets/bookmark_item/bookmark_item.dart b/lib/widgets/bookmark_item/bookmark_item.dart deleted file mode 100644 index 206df32..0000000 --- a/lib/widgets/bookmark_item/bookmark_item.dart +++ /dev/null @@ -1,281 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:linkdy/constants/urls.dart'; -import 'package:linkdy/widgets/bookmark_item/bookmark_context_menu.dart'; -import 'package:linkdy/widgets/bookmark_item/bookmark_slide_menu.dart'; -import 'package:skeletonizer/skeletonizer.dart'; - -import 'package:linkdy/i18n/strings.g.dart'; -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:linkdy/utils/date_to_string.dart'; - -class BookmarkItem extends ConsumerWidget { - final Bookmark bookmark; - final void Function(Bookmark bookmark) onSelect; - final void Function(Bookmark bookmark) onDelete; - final void Function(Bookmark bookmark) onReadUnread; - final void Function(Bookmark bookmark) onArchiveUnarchive; - final void Function(Bookmark bookmark) onEdit; - final void Function(Bookmark bookmark) onShareInternally; - final bool selected; - final bool tabletMode; - final Color? tileBackgroundColor; - - const BookmarkItem({ - super.key, - required this.bookmark, - required this.onSelect, - required this.onDelete, - required this.onReadUnread, - required this.onArchiveUnarchive, - required this.onEdit, - required this.onShareInternally, - required this.selected, - required this.tabletMode, - this.tileBackgroundColor, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Padding( - padding: tabletMode ? const EdgeInsets.symmetric(horizontal: 8) : const EdgeInsets.all(0), - child: ClipRRect( - borderRadius: tabletMode ? BorderRadius.circular(28) : BorderRadius.circular(0), - child: BookmarkSlideMenu( - bookmark: bookmark, - onSelect: onSelect, - onDelete: onDelete, - onReadUnread: onReadUnread, - onArchiveUnarchive: onArchiveUnarchive, - onEdit: onEdit, - onShareInternally: onShareInternally, - child: BookmarkContextMenu( - bookmark: bookmark, - onSelect: onSelect, - onDelete: onDelete, - onReadUnread: onReadUnread, - onArchiveUnarchive: onArchiveUnarchive, - onEdit: onEdit, - onShareInternally: onShareInternally, - child: _BookmarkContent( - bookmark: bookmark, - onSelect: onSelect, - selected: selected, - tabletMode: tabletMode, - tileBackgroundColor: tileBackgroundColor, - ), - ), - ), - ), - ); - } -} - -class _BookmarkContent extends ConsumerWidget { - final Bookmark bookmark; - final void Function(Bookmark bookmark) onSelect; - final bool selected; - final bool tabletMode; - final Color? tileBackgroundColor; - - const _BookmarkContent({ - required this.bookmark, - required this.onSelect, - required this.selected, - required this.tabletMode, - this.tileBackgroundColor, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - String validateStrings(String? string1, String? string2, String? string3) { - if (string1 != null && string1.isNotEmpty) { - return string1; - } else if (string2 != null && string2.isNotEmpty) { - return string2; - } else if (string3 != null && string3.isNotEmpty) { - return string3; - } else { - return ""; - } - } - - return Material( - color: selected && tabletMode - ? Theme.of(context).colorScheme.primaryContainer - : tileBackgroundColor ?? Theme.of(context).colorScheme.surface, - child: InkWell( - onTap: () => onSelect(bookmark), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - if (ref.watch(appStatusProvider).showFavicon == true) - Padding( - padding: const EdgeInsets.only(right: 8), - child: Image.network( - Urls.gstatic(bookmark.url), - width: 16, - height: 16, - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress != null) { - return ClipRRect( - borderRadius: BorderRadius.circular(4), - child: Skeletonizer( - enabled: true, - ignoreContainers: true, - child: Container( - width: 16, - height: 16, - color: Colors.black, - ), - ), - ); - } - return child; - }, - ), - ), - Expanded( - child: Text( - validateStrings(bookmark.title, bookmark.websiteTitle, bookmark.url), - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), - ], - ), - const SizedBox(height: 4), - Text( - validateStrings(bookmark.description, bookmark.websiteDescription, bookmark.url), - maxLines: 3, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: TextStyle( - fontSize: 14, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 3), - Row( - children: [ - Expanded( - child: Text( - bookmark.tagNames?.map((tag) => "#$tag").join(" ") ?? '', - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - ), - if (bookmark.shared == true) ...[ - if (bookmark.tagNames?.isNotEmpty == true) - Container( - width: 1, - height: 12, - margin: const EdgeInsets.symmetric(horizontal: 8), - color: Theme.of(context).colorScheme.tertiary.withOpacity(0.3), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Theme.of(context).colorScheme.primaryContainer, - ), - child: Row( - children: [ - Icon( - Icons.share_rounded, - size: 12, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - const SizedBox(width: 4), - Text( - t.bookmarks.bookmarkOptions.shared, - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.onPrimaryContainer, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ], - if (bookmark.unread == true) ...[ - if (bookmark.tagNames?.isNotEmpty == true || bookmark.shared == true) - Container( - width: 1, - height: 12, - margin: const EdgeInsets.symmetric(horizontal: 8), - color: Theme.of(context).colorScheme.tertiary.withOpacity(0.3), - ), - Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 2, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: Theme.of(context).colorScheme.primaryContainer, - ), - child: Row( - children: [ - Icon( - Icons.mark_as_unread_rounded, - size: 12, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - const SizedBox(width: 4), - Text( - t.bookmarks.bookmarkOptions.unread, - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.onPrimaryContainer, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ], - if (bookmark.dateModified != null) ...[ - if (bookmark.unread == true || bookmark.shared == true || bookmark.tagNames?.isNotEmpty == true) - Container( - width: 1, - height: 12, - margin: const EdgeInsets.symmetric(horizontal: 8), - color: Theme.of(context).colorScheme.tertiary.withOpacity(0.3), - ), - Text( - dateToString(bookmark.dateModified!), - style: TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ], - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/widgets/bookmark_item/bookmark_slide_menu.dart b/lib/widgets/bookmark_item/bookmark_slide_menu.dart deleted file mode 100644 index d0a791e..0000000 --- a/lib/widgets/bookmark_item/bookmark_slide_menu.dart +++ /dev/null @@ -1,154 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:linkdy/providers/app_status.provider.dart'; -import 'package:share_plus/share_plus.dart'; -import 'package:slideable/slideable.dart'; - -import 'package:linkdy/models/data/bookmarks.dart'; -import 'package:linkdy/i18n/strings.g.dart'; - -class BookmarkSlideMenu extends ConsumerWidget { - final Widget child; - final Bookmark bookmark; - final void Function(Bookmark bookmark) onSelect; - final void Function(Bookmark bookmark) onDelete; - final void Function(Bookmark bookmark) onReadUnread; - final void Function(Bookmark bookmark) onArchiveUnarchive; - final void Function(Bookmark bookmark) onEdit; - final void Function(Bookmark bookmark) onShareInternally; - - const BookmarkSlideMenu({ - super.key, - required this.bookmark, - required this.child, - required this.onSelect, - required this.onDelete, - required this.onReadUnread, - required this.onArchiveUnarchive, - required this.onEdit, - required this.onShareInternally, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - if (ref.watch(appStatusProvider).enableSlideOptions == true) { - return Slideable( - resetSlide: false, - items: [ - ActionItems( - icon: _ActionItemContent( - icon: Icon( - bookmark.unread == true ? Icons.mark_email_read_rounded : Icons.mark_as_unread_rounded, - color: Colors.white, - ), - text: bookmark.unread == true - ? t.bookmarks.bookmarkOptions.markAsRead - : t.bookmarks.bookmarkOptions.markAsUnread, - ), - onPress: () => onReadUnread(bookmark), - backgroudColor: Colors.green, - ), - ActionItems( - icon: _ActionItemContent( - icon: Icon( - bookmark.isArchived == true ? Icons.unarchive_rounded : Icons.archive_rounded, - color: Colors.white, - ), - text: bookmark.isArchived == true - ? t.bookmarks.bookmarkOptions.unarchive - : t.bookmarks.bookmarkOptions.archive, - ), - onPress: () => onArchiveUnarchive(bookmark), - backgroudColor: Colors.blueGrey, - ), - ActionItems( - icon: _ActionItemContent( - icon: Icon( - bookmark.shared == true ? Icons.person_remove_rounded : Icons.person_add_rounded, - color: Colors.white, - ), - text: bookmark.shared == true - ? t.bookmarks.bookmarkOptions.unshareInternally - : t.bookmarks.bookmarkOptions.shareInternally, - ), - onPress: () => onShareInternally(bookmark), - backgroudColor: Colors.teal, - ), - ActionItems( - icon: _ActionItemContent( - icon: Icon( - Icons.output_rounded, - color: Colors.white, - ), - text: t.bookmarks.bookmarkOptions.shareThirdPartyApp, - ), - onPress: () { - final box = context.findRenderObject() as RenderBox?; - Share.share( - bookmark.url!, - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, - ); - }, - backgroudColor: Colors.purple, - ), - ActionItems( - icon: _ActionItemContent( - icon: Icon( - Icons.edit_rounded, - color: Colors.white, - ), - text: t.bookmarks.bookmarkOptions.edit, - ), - onPress: () => onEdit(bookmark), - backgroudColor: Colors.blue, - ), - ActionItems( - icon: _ActionItemContent( - icon: Icon( - Icons.delete_rounded, - color: Colors.white, - ), - text: t.bookmarks.bookmarkOptions.delete, - ), - onPress: () => onDelete(bookmark), - backgroudColor: Colors.red, - ), - ], - child: child, - ); - } else { - return child; - } - } -} - -class _ActionItemContent extends StatelessWidget { - final Icon icon; - final String text; - - const _ActionItemContent({ - required this.icon, - required this.text, - }); - - @override - Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - icon, - SizedBox(height: 6), - Text( - text, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w700, - color: Colors.white, - ), - textAlign: TextAlign.center, - ), - ], - ); - } -} diff --git a/lib/widgets/circle_page_transition.dart b/lib/widgets/circle_page_transition.dart deleted file mode 100644 index deef076..0000000 --- a/lib/widgets/circle_page_transition.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:flutter/cupertino.dart'; - -class CirclePageRoute extends PageRouteBuilder { - final Widget page; - final Offset beginPosition; - - CirclePageRoute({ - required this.page, - required this.beginPosition, - }) : super( - pageBuilder: ( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - ) => - page, - ); - - @override - Widget buildTransitions( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - Widget child, - ) { - const double beganRadius = 0.0; - final size = MediaQuery.of(context).size; - final double endRadius = size.height > size.width ? size.height * 1.2 : size.width * 1.2; - - final radiusTweenAnimation = animation.drive( - Tween(begin: beganRadius, end: endRadius), - ); - - return ClipPath( - clipper: _CircleTransitionClipper( - center: beginPosition, - radius: radiusTweenAnimation.value, - ), - child: child, - ); - } -} - -class _CircleTransitionClipper extends CustomClipper { - final Offset center; - final double radius; - - const _CircleTransitionClipper({ - required this.center, - required this.radius, - }); - - @override - Path getClip(Size size) { - return Path() - ..addOval( - Rect.fromCircle( - center: center, - radius: radius, - ), - ); - } - - @override - bool shouldReclip(covariant CustomClipper oldClipper) => true; -} diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart deleted file mode 100644 index d92e2e3..0000000 --- a/lib/widgets/custom_list_tile.dart +++ /dev/null @@ -1,100 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomListTile extends StatelessWidget { - final String title; - final String? subtitle; - final Widget? subtitleWidget; - final void Function()? onTap; - final IconData? icon; - final Widget? trailing; - final EdgeInsets? padding; - final void Function()? onLongPress; - final bool? disabled; - final void Function(bool)? onHover; - final Color? color; - - const CustomListTile({ - super.key, - required this.title, - this.subtitle, - this.subtitleWidget, - this.onTap, - this.icon, - this.trailing, - this.padding, - this.onLongPress, - this.disabled, - this.onHover, - this.color, - }); - - @override - Widget build(BuildContext context) { - return Material( - color: color ?? Colors.transparent, - child: InkWell( - onTap: onTap, - onHover: onHover, - onLongPress: onLongPress, - child: Padding( - padding: padding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (icon != null) ...[ - Icon( - icon, - size: 24, - color: disabled == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - : Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 16), - ], - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: disabled == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - : Theme.of(context).colorScheme.onSurface, - ), - ), - if (subtitle != null || subtitleWidget != null) ...[ - const SizedBox(height: 5), - if (subtitle == null && subtitleWidget != null) subtitleWidget!, - if (subtitle != null && subtitleWidget == null) - Text( - subtitle!, - style: TextStyle( - color: disabled == true - ? Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.38) - : Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: 14, - fontWeight: FontWeight.w400, - ), - ), - ], - ], - ), - ), - ], - ), - ), - if (trailing != null) ...[const SizedBox(width: 16), trailing!], - ], - ), - ), - ), - ); - } -} diff --git a/lib/widgets/custom_settings_tile.dart b/lib/widgets/custom_settings_tile.dart deleted file mode 100644 index ee78fbc..0000000 --- a/lib/widgets/custom_settings_tile.dart +++ /dev/null @@ -1,100 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomSettingsTile extends StatelessWidget { - final String title; - final String? subtitle; - final Widget? subtitleWidget; - final void Function()? onTap; - final IconData? icon; - final Widget? trailing; - final EdgeInsets? padding; - final int thisItem; - final int? selectedItem; - - const CustomSettingsTile({ - super.key, - required this.title, - this.subtitle, - this.subtitleWidget, - this.onTap, - this.icon, - this.trailing, - this.padding, - required this.thisItem, - required this.selectedItem, - }); - - @override - Widget build(BuildContext context) { - Widget tileBody = Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (icon != null) ...[ - Icon( - icon, - size: 24, - color: Theme.of(context).listTileTheme.iconColor, - ), - const SizedBox(width: 16), - ], - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, - ), - ), - if (subtitle != null || subtitleWidget != null) ...[ - const SizedBox(height: 5), - if (subtitle == null && subtitleWidget != null) subtitleWidget!, - if (subtitle != null && subtitleWidget == null) - Text( - subtitle!, - style: TextStyle( - color: Theme.of(context).listTileTheme.textColor, - fontSize: 14, - fontWeight: FontWeight.w400, - ), - ), - ], - ], - ), - ), - ], - ), - ), - if (trailing != null) ...[const SizedBox(width: 10), trailing!], - ], - ); - - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(28), - child: InkWell( - borderRadius: BorderRadius.circular(28), - onTap: onTap, - child: Container( - width: double.maxFinite, - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(28), - color: thisItem == selectedItem ? Theme.of(context).colorScheme.primaryContainer : null, - ), - child: tileBody, - ), - ), - ), - ); - } -} diff --git a/lib/widgets/custom_switch_list_tile.dart b/lib/widgets/custom_switch_list_tile.dart deleted file mode 100644 index 8eb3875..0000000 --- a/lib/widgets/custom_switch_list_tile.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomSwitchListTile extends StatelessWidget { - final bool value; - final void Function(bool) onChanged; - final String title; - final String? subtitle; - final bool? disabled; - final EdgeInsets? padding; - final IconData? leadingIcon; - - const CustomSwitchListTile({ - super.key, - required this.value, - required this.onChanged, - required this.title, - this.disabled, - this.subtitle, - this.padding, - this.leadingIcon, - }); - - @override - Widget build(BuildContext context) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: disabled != null && disabled == true ? null : () => onChanged(!value), - child: Padding( - padding: padding ?? - const EdgeInsets.only( - top: 12, - left: 16, - right: 18, - bottom: 16, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (leadingIcon != null) ...[ - Icon( - leadingIcon, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(width: 16), - ], - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - fontSize: 16, - color: disabled != null && disabled == true - ? Theme.of(context).colorScheme.onSurface.withOpacity(0.38) - : Theme.of(context).colorScheme.onSurface, - ), - ), - if (subtitle != null) ...[ - const SizedBox(height: 5), - SizedBox( - width: MediaQuery.of(context).size.width - 110, - child: Text( - subtitle!, - style: TextStyle( - fontSize: 14, - color: disabled != null && disabled == true - ? Theme.of(context).listTileTheme.textColor!.withOpacity(0.38) - : Theme.of(context).listTileTheme.textColor, - ), - ), - ), - ], - ], - ), - ), - const SizedBox(width: 16), - Switch( - value: value, - onChanged: disabled != null && disabled == true ? null : onChanged, - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/widgets/enter_search_term_screen.dart b/lib/widgets/enter_search_term_screen.dart deleted file mode 100644 index d936791..0000000 --- a/lib/widgets/enter_search_term_screen.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/material.dart'; - -class EnterSearchTermScreen extends StatelessWidget { - final String message; - - const EnterSearchTermScreen({ - super.key, - required this.message, - }); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(24), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.search_rounded, - size: 50, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(height: 30), - Text( - message, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ), - ], - ), - ); - } -} diff --git a/lib/widgets/error_screen.dart b/lib/widgets/error_screen.dart deleted file mode 100644 index 55a5cdf..0000000 --- a/lib/widgets/error_screen.dart +++ /dev/null @@ -1,36 +0,0 @@ -import 'package:flutter/material.dart'; - -class ErrorScreen extends StatelessWidget { - final String error; - - const ErrorScreen({ - super.key, - required this.error, - }); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.error_rounded, - size: 50, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(height: 30), - Text( - error, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ); - } -} diff --git a/lib/widgets/layout.dart b/lib/widgets/layout.dart deleted file mode 100644 index 6ed995e..0000000 --- a/lib/widgets/layout.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -import 'package:linkdy/widgets/system_overlay_style.dart'; - -import 'package:linkdy/config/app_screens.dart'; -import 'package:linkdy/providers/router.provider.dart'; - -class Layout extends ConsumerWidget { - final GoRouterState state; - final Widget child; - - const Layout({ - super.key, - required this.state, - required this.child, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final screenIndex = appScreens.map((s) => s.route).toList().indexOf("/${state.matchedLocation.split("/")[1]}"); - - return OverlayStyle( - child: Scaffold( - body: child, - bottomNavigationBar: NavigationBar( - onDestinationSelected: (s) => ref.watch(routerProvider).replace(appScreens[s].route), - selectedIndex: screenIndex, - destinations: appScreens - .map( - (screen) => NavigationDestination( - icon: Icon(screen.icon), - label: screen.name, - ), - ) - .toList(), - ), - ), - ); - } -} diff --git a/lib/widgets/no_data_screen.dart b/lib/widgets/no_data_screen.dart deleted file mode 100644 index 650955f..0000000 --- a/lib/widgets/no_data_screen.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/material.dart'; - -class NoDataScreen extends StatelessWidget { - final String message; - - const NoDataScreen({ - super.key, - required this.message, - }); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(16), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.clear_all_rounded, - size: 50, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - const SizedBox(height: 30), - Text( - message, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - ], - ), - ), - ], - ), - ); - } -} diff --git a/lib/widgets/page_transition.dart b/lib/widgets/page_transition.dart deleted file mode 100644 index 7042183..0000000 --- a/lib/widgets/page_transition.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:animations/animations.dart'; - -class PageTransition extends StatelessWidget { - final Widget child; - - const PageTransition({ - super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return PageTransitionSwitcher( - duration: const Duration(milliseconds: 200), - transitionBuilder: (child, primaryAnimation, secondaryAnimation) => FadeThroughTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - child: child, - ), - child: child, - ); - } -} diff --git a/lib/widgets/process_dialog.dart b/lib/widgets/process_dialog.dart deleted file mode 100644 index 7e08f76..0000000 --- a/lib/widgets/process_dialog.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/material.dart'; - -class ProcessDialog extends StatelessWidget { - final String message; - - const ProcessDialog({ - super.key, - required this.message, - }); - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async => false, - child: Dialog( - backgroundColor: Theme.of(context).dialogBackgroundColor, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 30, - horizontal: 30, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const CircularProgressIndicator(), - const SizedBox(width: 40), - Flexible( - child: Text( - message, - style: TextStyle(color: Theme.of(context).colorScheme.onSurface), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/widgets/section_label.dart b/lib/widgets/section_label.dart deleted file mode 100644 index 26a31a8..0000000 --- a/lib/widgets/section_label.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter/material.dart'; - -class SectionLabel extends StatelessWidget { - final String label; - final EdgeInsets? padding; - - const SectionLabel({ - super.key, - required this.label, - this.padding, - }); - - @override - Widget build(BuildContext context) { - return Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: padding ?? const EdgeInsets.all(16), - child: Text( - label, - style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16, color: Theme.of(context).colorScheme.primary), - ), - ), - ], - ); - } -} diff --git a/lib/widgets/sliver_tab_body.dart b/lib/widgets/sliver_tab_body.dart deleted file mode 100644 index 10b41bb..0000000 --- a/lib/widgets/sliver_tab_body.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:flutter/material.dart'; - -class SliverTabBody extends StatelessWidget { - final Widget child; - - const SliverTabBody({super.key, required this.child}); - - @override - Widget build(BuildContext context) { - return SafeArea( - top: false, - child: Builder( - builder: (BuildContext context) => CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - child, - ], - ), - ), - ); - } -} - -class SliverTabBodyRefresh extends StatelessWidget { - final Widget child; - final Future Function() onRefresh; - - const SliverTabBodyRefresh({ - super.key, - required this.child, - required this.onRefresh, - }); - - @override - Widget build(BuildContext context) { - return SafeArea( - top: false, - child: Builder( - builder: (BuildContext context) => RefreshIndicator( - displacement: 120, - onRefresh: onRefresh, - child: CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), - ), - child, - ], - ), - ), - ), - ); - } -} diff --git a/lib/widgets/system_overlay_style.dart b/lib/widgets/system_overlay_style.dart deleted file mode 100644 index aaf614a..0000000 --- a/lib/widgets/system_overlay_style.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -class OverlayStyle extends StatelessWidget { - final Widget child; - - const OverlayStyle({ - super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - final systemGestureInsets = MediaQuery.of(context).systemGestureInsets; - - return AnnotatedRegion( - value: SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.light : Brightness.dark, - statusBarIconBrightness: Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light, - systemNavigationBarColor: systemGestureInsets.left > 0 // If true gestures navigation - ? Colors.transparent - : ElevationOverlay.applySurfaceTint( - Theme.of(context).colorScheme.surface, - Theme.of(context).colorScheme.surfaceTint, - 3, - ), - systemNavigationBarIconBrightness: - Theme.of(context).brightness == Brightness.light ? Brightness.dark : Brightness.light, - ), - child: child, - ); - } -} diff --git a/project.yml b/project.yml new file mode 100644 index 0000000..ea063ef --- /dev/null +++ b/project.yml @@ -0,0 +1,61 @@ +name: Marks + +options: + bundleIdPrefix: com.magicive + deploymentTarget: + iOS: "26.0" + xcodeVersion: "16.3" + createIntermediateGroups: true + +settings: + base: + SWIFT_VERSION: "6.0" + DEVELOPMENT_TEAM: AE5DZKJHGN + CODE_SIGN_STYLE: Automatic + IPHONEOS_DEPLOYMENT_TARGET: "26.0" + ENABLE_PREVIEWS: YES + +schemes: + Marks: + build: + targets: + Marks: all + ShareExtension: all + run: + config: Debug + test: + config: Debug + profile: + config: Release + analyze: + config: Debug + archive: + config: Release + +targets: + Marks: + type: application + platform: iOS + sources: + - path: Marks + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: com.magicive.marks + INFOPLIST_FILE: Marks/Info.plist + CODE_SIGN_ENTITLEMENTS: Marks/Marks.entitlements + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon + dependencies: + - target: ShareExtension + + ShareExtension: + type: app-extension + platform: iOS + sources: + - path: ShareExtension + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: com.magicive.marks.ShareExtension + INFOPLIST_FILE: ShareExtension/Info.plist + CODE_SIGN_ENTITLEMENTS: ShareExtension/ShareExtension.entitlements + SKIP_INSTALL: YES + APPLICATION_EXTENSION_API_ONLY: YES diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index 7a33a16..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,1375 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f - url: "https://pub.dev" - source: hosted - version: "85.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c - url: "https://pub.dev" - source: hosted - version: "7.6.0" - analyzer_plugin: - dependency: transitive - description: - name: analyzer_plugin - sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce - url: "https://pub.dev" - source: hosted - version: "0.13.4" - animations: - dependency: "direct main" - description: - name: animations - sha256: "9cb469212ea51be27097f23b519d594c01171721347b55df9334fff653659e7f" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - ansicolor: - dependency: transitive - description: - name: ansicolor - sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" - url: "https://pub.dev" - source: hosted - version: "2.0.3" - archive: - dependency: transitive - description: - name: archive - sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff - url: "https://pub.dev" - source: hosted - version: "4.0.9" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" - source: hosted - version: "2.13.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - build: - dependency: transitive - description: - name: build - sha256: "51dc711996cbf609b90cbe5b335bbce83143875a9d58e4b5c6d3c4f684d3dda7" - url: "https://pub.dev" - source: hosted - version: "2.5.4" - build_config: - dependency: transitive - description: - name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - build_daemon: - dependency: transitive - description: - name: build_daemon - sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 - url: "https://pub.dev" - source: hosted - version: "4.1.1" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - sha256: ee4257b3f20c0c90e72ed2b57ad637f694ccba48839a821e87db762548c22a62 - url: "https://pub.dev" - source: hosted - version: "2.5.4" - build_runner: - dependency: "direct dev" - description: - name: build_runner - sha256: "382a4d649addbfb7ba71a3631df0ec6a45d5ab9b098638144faf27f02778eb53" - url: "https://pub.dev" - source: hosted - version: "2.5.4" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - sha256: "85fbbb1036d576d966332a3f5ce83f2ce66a40bea1a94ad2d5fc29a19a0d3792" - url: "https://pub.dev" - source: hosted - version: "9.1.2" - built_collection: - dependency: transitive - description: - name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" - source: hosted - version: "5.1.1" - built_value: - dependency: transitive - description: - name: built_value - sha256: "34e4067d30ce212937df995f03b69992eea683539ceeac7f679a1f1eba055b56" - url: "https://pub.dev" - source: hosted - version: "8.12.6" - characters: - dependency: transitive - description: - name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b - url: "https://pub.dev" - source: hosted - version: "1.4.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.dev" - source: hosted - version: "2.0.4" - ci: - dependency: transitive - description: - name: ci - sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" - url: "https://pub.dev" - source: hosted - version: "0.1.0" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.dev" - source: hosted - version: "0.4.2" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - code_assets: - dependency: transitive - description: - name: code_assets - sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - code_builder: - dependency: transitive - description: - name: code_builder - sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" - url: "https://pub.dev" - source: hosted - version: "4.11.1" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" - url: "https://pub.dev" - source: hosted - version: "0.3.5+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" - source: hosted - version: "3.0.7" - csslib: - dependency: transitive - description: - name: csslib - sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" - url: "https://pub.dev" - source: hosted - version: "1.0.9" - custom_lint: - dependency: "direct dev" - description: - name: custom_lint - sha256: "409c485fd14f544af1da965d5a0d160ee57cd58b63eeaa7280a4f28cf5bda7f1" - url: "https://pub.dev" - source: hosted - version: "0.7.5" - custom_lint_builder: - dependency: transitive - description: - name: custom_lint_builder - sha256: "107e0a43606138015777590ee8ce32f26ba7415c25b722ff0908a6f5d7a4c228" - url: "https://pub.dev" - source: hosted - version: "0.7.5" - custom_lint_core: - dependency: transitive - description: - name: custom_lint_core - sha256: "31110af3dde9d29fb10828ca33f1dce24d2798477b167675543ce3d208dee8be" - url: "https://pub.dev" - source: hosted - version: "0.7.5" - custom_lint_visitor: - dependency: transitive - description: - name: custom_lint_visitor - sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2" - url: "https://pub.dev" - source: hosted - version: "1.0.0+7.7.0" - dart_style: - dependency: transitive - description: - name: dart_style - sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - dio: - dependency: "direct main" - description: - name: dio - sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c - url: "https://pub.dev" - source: hosted - version: "5.9.2" - dio_web_adapter: - dependency: transitive - description: - name: dio_web_adapter - sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - dynamic_color: - dependency: "direct main" - description: - name: dynamic_color - sha256: "43a5a6679649a7731ab860334a5812f2067c2d9ce6452cf069c5e0c25336c17c" - url: "https://pub.dev" - source: hosted - version: "1.8.1" - easy_autocomplete: - dependency: "direct main" - description: - name: easy_autocomplete - sha256: e7ded95deb010daec41caf25f553b450fbdaa6769e7a6fdb7b8dce6764318406 - url: "https://pub.dev" - source: hosted - version: "1.6.0" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_custom_tabs: - dependency: "direct main" - description: - name: flutter_custom_tabs - sha256: "8c3d92b074a8109f1dc76333c5ff8f87ea5896c118264c4b6b6e7d880058e820" - url: "https://pub.dev" - source: hosted - version: "2.5.0" - flutter_custom_tabs_android: - dependency: transitive - description: - name: flutter_custom_tabs_android - sha256: "84e6b856fae8ca347bf47156f2106aac5671441fd6b3c531d1b793d22d29dece" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - flutter_custom_tabs_ios: - dependency: transitive - description: - name: flutter_custom_tabs_ios - sha256: "5f8bbfedad7ff60da4875d888085c05b1d0fd90acbfa4a624ae71b78c5cc6e37" - url: "https://pub.dev" - source: hosted - version: "2.5.0" - flutter_custom_tabs_platform_interface: - dependency: transitive - description: - name: flutter_custom_tabs_platform_interface - sha256: "2b66c541f3ca87fbf3e63808dbd41b28cb76f512acce5940f2468b33abe69031" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - flutter_custom_tabs_web: - dependency: transitive - description: - name: flutter_custom_tabs_web - sha256: d606b231859c79679c78dbf05293528a543e3e067c2893a3a5bed1ab9a8300bb - url: "https://pub.dev" - source: hosted - version: "2.4.0" - flutter_dotenv: - dependency: "direct main" - description: - name: flutter_dotenv - sha256: d41da11fb497314fbf89811ec30af02d1d898b47980a129f0a8c0a1720460ba2 - url: "https://pub.dev" - source: hosted - version: "6.0.1" - flutter_hooks: - dependency: "direct main" - description: - name: flutter_hooks - sha256: "8ae1f090e5f4ef5cfa6670ce1ab5dddadd33f3533a7f9ba19d9f958aa2a89f42" - url: "https://pub.dev" - source: hosted - version: "0.21.3+1" - flutter_launcher_icons: - dependency: "direct dev" - description: - name: flutter_launcher_icons - sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" - url: "https://pub.dev" - source: hosted - version: "0.14.4" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_localizations: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_native_splash: - dependency: "direct dev" - description: - name: flutter_native_splash - sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002" - url: "https://pub.dev" - source: hosted - version: "2.4.7" - flutter_riverpod: - dependency: "direct main" - description: - name: flutter_riverpod - sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" - url: "https://pub.dev" - source: hosted - version: "2.6.1" - flutter_svg: - dependency: "direct main" - description: - name: flutter_svg - sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f" - url: "https://pub.dev" - source: hosted - version: "2.3.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: "92d8cee7c57dff0a6c409c05597b460002434eccf7424a712283225b3962d03f" - url: "https://pub.dev" - source: hosted - version: "17.2.3" - graphs: - dependency: transitive - description: - name: graphs - sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - hooks: - dependency: transitive - description: - name: hooks - sha256: "025f060e86d2d4c3c47b56e33caf7f93bf9283340f26d23424ebcfccf34f621e" - url: "https://pub.dev" - source: hosted - version: "1.0.3" - hooks_riverpod: - dependency: "direct main" - description: - name: hooks_riverpod - sha256: "70bba33cfc5670c84b796e6929c54b8bc5be7d0fe15bb28c2560500b9ad06966" - url: "https://pub.dev" - source: hosted - version: "2.6.1" - hotreloader: - dependency: transitive - description: - name: hotreloader - sha256: "66871df468fc24eee81f1a0a7cb98acc104716f9b7376d355437b48d633c4ebf" - url: "https://pub.dev" - source: hosted - version: "4.4.0" - html: - dependency: transitive - description: - name: html - sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" - url: "https://pub.dev" - source: hosted - version: "0.15.6" - http: - dependency: "direct main" - description: - name: http - sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - image: - dependency: transitive - description: - name: image - sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce - url: "https://pub.dev" - source: hosted - version: "4.8.0" - intl: - dependency: transitive - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - jni: - dependency: transitive - description: - name: jni - sha256: d2c361082d554d4593c3012e26f6b188f902acd291330f13d6427641a92b3da1 - url: "https://pub.dev" - source: hosted - version: "0.14.2" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 - url: "https://pub.dev" - source: hosted - version: "4.11.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - listen_sharing_intent: - dependency: "direct main" - description: - name: listen_sharing_intent - sha256: df12e6c78666018985c39df494fc12412ece6510c38c79fe1230f2abef0965fa - url: "https://pub.dev" - source: hosted - version: "1.9.2" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 - url: "https://pub.dev" - source: hosted - version: "0.12.19" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" - url: "https://pub.dev" - source: hosted - version: "0.13.0" - meta: - dependency: transitive - description: - name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" - source: hosted - version: "1.17.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - native_toolchain_c: - dependency: transitive - description: - name: native_toolchain_c - sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" - url: "https://pub.dev" - source: hosted - version: "0.17.6" - objective_c: - dependency: transitive - description: - name: objective_c - sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" - url: "https://pub.dev" - source: hosted - version: "9.3.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" - package_info_plus: - dependency: "direct main" - description: - name: package_info_plus - sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20" - url: "https://pub.dev" - source: hosted - version: "9.0.1" - package_info_plus_platform_interface: - dependency: transitive - description: - name: package_info_plus_platform_interface - sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba" - url: "https://pub.dev" - source: hosted - version: "2.2.23" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" - url: "https://pub.dev" - source: hosted - version: "2.6.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" - url: "https://pub.dev" - source: hosted - version: "7.0.2" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" - posix: - dependency: transitive - description: - name: posix - sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" - url: "https://pub.dev" - source: hosted - version: "6.5.0" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" - url: "https://pub.dev" - source: hosted - version: "1.5.0" - record_use: - dependency: transitive - description: - name: record_use - sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" - url: "https://pub.dev" - source: hosted - version: "0.6.0" - riverpod: - dependency: transitive - description: - name: riverpod - sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" - url: "https://pub.dev" - source: hosted - version: "2.6.1" - riverpod_analyzer_utils: - dependency: transitive - description: - name: riverpod_analyzer_utils - sha256: "03a17170088c63aab6c54c44456f5ab78876a1ddb6032ffde1662ddab4959611" - url: "https://pub.dev" - source: hosted - version: "0.5.10" - riverpod_annotation: - dependency: "direct main" - description: - name: riverpod_annotation - sha256: e14b0bf45b71326654e2705d462f21b958f987087be850afd60578fcd502d1b8 - url: "https://pub.dev" - source: hosted - version: "2.6.1" - riverpod_generator: - dependency: "direct dev" - description: - name: riverpod_generator - sha256: "44a0992d54473eb199ede00e2260bd3c262a86560e3c6f6374503d86d0580e36" - url: "https://pub.dev" - source: hosted - version: "2.6.5" - riverpod_lint: - dependency: "direct dev" - description: - name: riverpod_lint - sha256: "89a52b7334210dbff8605c3edf26cfe69b15062beed5cbfeff2c3812c33c9e35" - url: "https://pub.dev" - source: hosted - version: "2.6.5" - rxdart: - dependency: transitive - description: - name: rxdart - sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" - url: "https://pub.dev" - source: hosted - version: "0.28.0" - segmented_button_slide: - dependency: "direct main" - description: - name: segmented_button_slide - sha256: "96d67344fa65f6b98a317d930bfd4e81e47c4f9e3e2ab1ee8925b55f72cded13" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - sentry: - dependency: transitive - description: - name: sentry - sha256: f04095a25ff02b202a914174c73ec309570aa93d61098cb4a0a9e715b4aaa465 - url: "https://pub.dev" - source: hosted - version: "9.20.0" - sentry_flutter: - dependency: "direct main" - description: - name: sentry_flutter - sha256: "4f0a914d8c37e5015d7b86dd42b92dd265948fd31875b43e62ddfc2e7bea0e41" - url: "https://pub.dev" - source: hosted - version: "9.20.0" - serial_csv: - dependency: transitive - description: - name: serial_csv - sha256: "2d62bb70cb3ce7251383fc86ea9aae1298ab1e57af6ef4e93b6a9751c5c268dd" - url: "https://pub.dev" - source: hosted - version: "0.5.2" - share_plus: - dependency: "direct main" - description: - name: share_plus - sha256: "223873d106614442ea6f20db5a038685cc5b32a2fba81cdecaefbbae0523f7fa" - url: "https://pub.dev" - source: hosted - version: "12.0.2" - share_plus_platform_interface: - dependency: transitive - description: - name: share_plus_platform_interface - sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf - url: "https://pub.dev" - source: hosted - version: "2.5.5" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53 - url: "https://pub.dev" - source: hosted - version: "2.4.23" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" - url: "https://pub.dev" - source: hosted - version: "2.5.6" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" - url: "https://pub.dev" - source: hosted - version: "2.4.2" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" - source: hosted - version: "2.4.3" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - skeletonizer: - dependency: "direct main" - description: - name: skeletonizer - sha256: "9f38f9b47ec3cf2235a6a4f154a88a95432bc55ba98b3e2eb6ced5c1974bc122" - url: "https://pub.dev" - source: hosted - version: "2.1.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - slang: - dependency: "direct main" - description: - name: slang - sha256: ea6702ed6b1c82065fb2de906fe34ac9298117342e3c2ea2567132efdc81bd17 - url: "https://pub.dev" - source: hosted - version: "4.14.0" - slang_build_runner: - dependency: "direct dev" - description: - name: slang_build_runner - sha256: "1db59254041026aec97df5aca30a602e09e9d1546c3d16b55c3c7cf4c16cdb6c" - url: "https://pub.dev" - source: hosted - version: "4.14.0" - slang_flutter: - dependency: "direct main" - description: - name: slang_flutter - sha256: dcc4e77527c91b12348fc8bdd43d3eb92d8cea37c12a23a1f9719cdc12c804c6 - url: "https://pub.dev" - source: hosted - version: "4.14.0" - slideable: - dependency: "direct main" - description: - name: slideable - sha256: "6ab04552c1fba1767e91f09d6e3bc6acf69d87c0fadb8c19656f621ffd93fdf6" - url: "https://pub.dev" - source: hosted - version: "0.0.3" - source_gen: - dependency: transitive - description: - name: source_gen - sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" - source: hosted - version: "1.10.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - state_notifier: - dependency: transitive - description: - name: state_notifier - sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb - url: "https://pub.dev" - source: hosted - version: "1.0.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" - url: "https://pub.dev" - source: hosted - version: "0.7.10" - timing: - dependency: transitive - description: - name: timing - sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" - url: "https://pub.dev" - source: hosted - version: "1.0.2" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - universal_io: - dependency: transitive - description: - name: universal_io - sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 - url: "https://pub.dev" - source: hosted - version: "2.3.1" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.dev" - source: hosted - version: "6.3.2" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572" - url: "https://pub.dev" - source: hosted - version: "6.3.29" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" - url: "https://pub.dev" - source: hosted - version: "6.4.1" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a - url: "https://pub.dev" - source: hosted - version: "3.2.2" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" - url: "https://pub.dev" - source: hosted - version: "3.2.5" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34" - url: "https://pub.dev" - source: hosted - version: "2.4.3" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" - url: "https://pub.dev" - source: hosted - version: "3.1.5" - uuid: - dependency: "direct main" - description: - name: uuid - sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" - url: "https://pub.dev" - source: hosted - version: "4.5.3" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: "4d35a36400983c3457c289d4d553b5308f506ea84f7e51c7a564651b5525209a" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: "98e7e94de127b46a86ef46197fff84ff99f3d3b80a708390d717ad731efef598" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" - url: "https://pub.dev" - source: hosted - version: "15.2.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webview_flutter: - dependency: "direct main" - description: - name: webview_flutter - sha256: a3da219916aba44947d3a5478b1927876a09781174b5a2b67fa5be0555154bf9 - url: "https://pub.dev" - source: hosted - version: "4.13.1" - webview_flutter_android: - dependency: transitive - description: - name: webview_flutter_android - sha256: ad5182eff9a550925330cb9f0cb038eddfdd5712aba8b77aa0f0400e50f6e688 - url: "https://pub.dev" - source: hosted - version: "4.12.0" - webview_flutter_platform_interface: - dependency: transitive - description: - name: webview_flutter_platform_interface - sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04" - url: "https://pub.dev" - source: hosted - version: "2.15.1" - webview_flutter_wkwebview: - dependency: transitive - description: - name: webview_flutter_wkwebview - sha256: "82648217f537573e1ca9ae9952d3eacedca6ab5aee69dc84445fc763766dcea2" - url: "https://pub.dev" - source: hosted - version: "3.25.1" - win32: - dependency: transitive - description: - name: win32 - sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.dev" - source: hosted - version: "5.15.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xml: - dependency: transitive - description: - name: xml - sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.dev" - source: hosted - version: "6.6.1" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.10.3 <4.0.0" - flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml deleted file mode 100644 index 5b1006b..0000000 --- a/pubspec.yaml +++ /dev/null @@ -1,133 +0,0 @@ -name: linkdy -description: "Linkding client." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. -version: 1.8.1+25 - -environment: - sdk: '>=3.2.6 <4.0.0' - -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. -dependencies: - flutter: - sdk: flutter - flutter_localizations: - sdk: flutter - cupertino_icons: ^1.0.8 - flutter_riverpod: 2.6.1 - go_router: ^17.0.0 - riverpod_annotation: 2.6.1 - dynamic_color: ^1.8.1 - shared_preferences: ^2.5.3 - url_launcher: ^6.3.2 - animations: ^2.1.1 - segmented_button_slide: 1.0.4 - dio: ^5.9.0 - uuid: ^4.5.2 - slang: ^4.7.2 - slang_flutter: ^4.7.0 - flutter_svg: ^2.2.3 - flutter_custom_tabs: ^2.4.0 - share_plus: ^12.0.2 - package_info_plus: ^9.0.1 - easy_autocomplete: ^1.6.0 - sentry_flutter: ^9.8.0 - flutter_dotenv: ^6.0.0 - skeletonizer: ^2.1.0+1 - http: ^1.6.0 - webview_flutter: ^4.13.0 - flutter_hooks: ^0.21.2 - hooks_riverpod: 2.6.1 - listen_sharing_intent: ^1.9.2 - slideable: ^0.0.3 - -dev_dependencies: - build_runner: ^2.5.1 - custom_lint: 0.7.5 - flutter_lints: ^6.0.0 - flutter_test: - sdk: flutter - riverpod_generator: 2.6.5 - riverpod_lint: 2.6.5 - slang_build_runner: ^4.7.0 - flutter_native_splash: ^2.4.6 - flutter_launcher_icons: ^0.14.4 - -flutter_icons: - ios: true - android: false - remove_alpha_ios: true - image_path_ios: "assets/icon/icon1024-background.png" - -flutter_native_splash: - color: "#ffffff" - image: assets/icon/icon-splash.png - color_dark: "#121212" - image_dark: assets/icon/icon-splash.png - - android_12: - color: "#ffffff" - image: assets/icon/icon-splash.png - color_dark: "#121212" - image_dark: assets/icon/icon-splash.png - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - assets: - - assets/resources/github.svg - - assets/resources/google-play.svg - - assets/icon/icon1024.png - - assets/icon/icon-splash.png - - assets/icon/icon1024-background.png - - .env - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages