commit 22f1ff7cd7d4d4750eeda2067d23846900239b83 Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat May 20 11:29:01 2023 -0700 fix: actually disable LocalConsole's character limit commit 4b51915da7bc0637ccf819ac45c7d727d450ae12 Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat May 20 11:27:12 2023 -0700 Merge SwiftUI improvements (#265) commit7f73f2adefMerge:72f34dd238a1c7eeAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat May 20 11:23:07 2023 -0700 Merge remote-tracking branch 'origin/fabianthdev/feature/SwiftUI' into naturecodevoid/swiftui-improvements commit72f34dd286Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Apr 12 18:21:49 2023 -0700 feat: default to Storm icon for PR builds Signed-off-by: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> commit060c37c423Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 19:40:53 2023 -0700 fix(icons): sky appears correctly in light mode commit8c2968aeb3Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 14:29:03 2023 -0700 fix: build errors commit4f512b6318Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:54:01 2023 -0700 project(minimuxer): fix actions build error commit5b752cf26eAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:51:54 2023 -0700 fix: remove duplicate isSideStore checks with a StoreApp extension commit62a478277eAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:41:58 2023 -0700 fix(AsyncFallibleButton): try to use failureReason and then fallback to localizedDescription commit994b2318a9Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:38:44 2023 -0700 feat(dev mode): add AFC file explorer and dump profiles commit423ac28ba3Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:35:14 2023 -0700 project(AltStore): xcode wants to move these around I guess commitaf2cdd48d6Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:34:57 2023 -0700 feat: add debug logging toggle commit44fe0c5686Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:33:11 2023 -0700 project(minimuxer): Add libminimuxer as an input file for build step commit3d46a3069aAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:32:22 2023 -0700 fix: handle source conflict in merge policy commit82e8fb7389Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Apr 9 13:31:39 2023 -0700 docs: include info on Developer Mode commit1dd0cd7d90Merge:92a9650c566841a9Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Apr 6 21:07:33 2023 -0700 Merge branch 'fabianthdev/feature/SwiftUI' into naturecodevoid/swiftui-improvements commit566841a9a6Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Apr 6 21:06:07 2023 -0700 Fix not being able to open the project commit92a9650c0cAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Apr 6 20:49:49 2023 -0700 Apply DevModeView suggestion commitdf94e79472Merge:d3cfc4bacd2c5ad7Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Apr 6 20:48:52 2023 -0700 Merge branch 'fabianthdev/feature/SwiftUI' into naturecodevoid/swiftui-improvements commitcd2c5ad7b4Merge:3466870d6146f1bdAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Apr 6 20:43:10 2023 -0700 Merge remote-tracking branch 'origin/develop' into fabianthdev/feature/SwiftUI commitd3cfc4bab9Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 22 13:05:11 2023 -0800 FileExplorer: Replace file when inserting commitdf62461d4aAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 22 13:04:52 2023 -0800 Settings: Add Export Logs and commit xcodeproj changes commit817d2de5e0Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 22 12:19:07 2023 -0800 Rename View+SideStore commit3ea478ad05Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 22 12:18:42 2023 -0800 DevMode: Add password commit13f9a9d1bfAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 22 11:43:13 2023 -0800 AdvancedSettingsView: improve anisette URL by using a label instead of a placeholder commit3821a6034dAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue Feb 21 17:34:56 2023 -0800 project: attempt to fix crashing on launch commit3e8d7da0c3Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 13:49:22 2023 -0800 AdvancedSettingsView: Remove autocomplete from anisette URL text field commita42c1a705fAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 13:25:59 2023 -0800 SettingsView: Adjust ordering a little bit and remove accent color commit30efc6f210Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 13:19:26 2023 -0800 LaunchViewController: Revert changes commit60412721eeAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 13:04:42 2023 -0800 Fix build errors hopefully this doesn't have any unintended side effects commitcba00a3b9dAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 12:03:22 2023 -0800 Add Advanced Settings in-app commit2aa880d10eAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 10:56:01 2023 -0800 Fix build errors after merge commit47848ddd18Merge:deac960e3466870dAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 09:56:21 2023 -0800 Merge branch 'fabianthdev/feature/SwiftUI' into naturecodevoid/swiftui-improvements Signed-off-by: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> commitdeac960e10Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 09:54:56 2023 -0800 Revert OutputCapturer changes since Fabian already added the fix commit9f05123e42Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 09:16:49 2023 -0800 AppIconView: Make isSideStore required commitd9a4b07095Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 09:16:07 2023 -0800 Fix changing SideStore app icon not displaying My Apps commit839699ee03Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 09:00:19 2023 -0800 Icons: add Vista by Swifticul commit81409227d6Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 08:06:33 2023 -0800 Add developer mode commit49b9be160fAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sun Feb 19 07:57:29 2023 -0800 AppRowView: Disable ratings if there aren't any ratings commit3466870d8fAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 14:31:01 2023 +0100 [ADD] UI for writing an app review and submit an app rating commitffe8a92a4eAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 14:30:21 2023 +0100 [CHANGE] UI fixes and SwiftUI previews for easier development commitbc2cae46a8Author: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 14:25:13 2023 +0100 [ADD] Refresh all apps functionality in MyAppsView commita95d8a502cAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 11:40:26 2023 +0100 [FIX] STDOUT output not visible in Xcode console commit19e66112ddAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat Feb 18 20:27:06 2023 -0800 SourcesView: Fix 1 trusted source causing an error making all trusted sources fail to load commit0d3cb843eaAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat Feb 18 20:26:32 2023 -0800 SourcesViewController: Fix 1 trusted source causing an error making all trusted sources fail to load commitdf1a662accAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat Feb 18 20:25:58 2023 -0800 FetchTrustedSourcesOperation: Remove redundant if statement commit684c9e08ebAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Sat Feb 18 10:48:05 2023 -0800 Fix HMR commitc585c57965Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Fri Feb 17 18:51:06 2023 -0800 Revert fixes since it didn't actually fix the problem commit3605ca6422Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Fri Feb 17 18:20:56 2023 -0800 Fix HMR again commit40f4c94f4dAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Fri Feb 17 18:11:25 2023 -0800 Fix HMR crashing the app commit986465d8f4Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Fri Feb 17 17:44:56 2023 -0800 Project: Add HMR https://github.com/krzysztofzablocki/Inject#individual-developer-setup-once-per-machine commit09db1ba9fcAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Feb 16 18:13:32 2023 -0800 SettingsView: Move App Icon to a new, general settings section commit8874480b8cAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Feb 16 17:57:51 2023 -0800 Icons: invert Sky commitf0cc4613daAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Thu Feb 16 17:57:19 2023 -0800 AppIconsView: Add artists commitbec78322a4Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 15 21:00:28 2023 -0800 actions: Add build step that changes default icon commit03777fd2e7Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 15 20:49:07 2023 -0800 Icons: add Sky, Honeydew, Midnight commit96ae60a9f2Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 15 19:36:10 2023 -0800 AppIconsView: improve the way primary icons are handled commitc7ad6b10a1Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 15 19:35:57 2023 -0800 Icons: reduce image sizes commit8b8e471c97Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Wed Feb 15 18:52:42 2023 -0800 Add App Icon changer commit38c0a8a9a3Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue Feb 14 08:24:49 2023 -0800 Fix ConnectAppleIDView being shoved into a sidebar on iPad commite7ff6496c1Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Tue Feb 14 08:20:16 2023 -0800 AuthenticationOperation: fix 2FA code not being displayed Bandaid fix, it would be better to have the alert in ConnectAppleIDView commitc2e89b09eaAuthor: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon Feb 13 21:44:48 2023 -0800 RootView: Fix UI being shoved into sidebar on iPad (closes #264, thanks @Swifticul!) commitec4dbb6679Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon Feb 13 21:06:59 2023 -0800 OutputCapturer: fix logging disappearing from Xcode/idevicedebug run commitd80c9ba2a8Author: naturecodevoid <44983869+naturecodevoid@users.noreply.github.com> Date: Mon Feb 13 21:06:17 2023 -0800 remove unused apps.json files commitb2f81bf7c6Author: Fabian Thies <git@fabian-thies.de> Date: Mon Feb 13 18:56:34 2023 +0100 [ADD] LocalConsole showing STDOUT and STDERR commit2fffa6e122Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 14:35:58 2023 +0100 [FIX] App compatibility info commit723c8e9539Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 14:29:02 2023 +0100 [ADD] Debug entries for refresh attempts, sending feedback, advanced settings, and resetting the pairing file commit07159b0ea6Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 13:07:04 2023 +0100 [ADD] Error log view commite0bd54389cAuthor: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 12:55:25 2023 +0100 [FIX] Various UI issues commit57213fbf0cAuthor: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 12:46:43 2023 +0100 [ADD] App report button and trusted source badge in app detail view commit0239dfcd6dAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Feb 3 18:19:07 2023 +0100 [FIX] AppIDsView and authentication workflow commit5af6f825eeAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Feb 3 18:16:48 2023 +0100 [FIX] Full screen app screenshot previews commitb4859512abAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Feb 3 14:58:06 2023 +0100 [FIX] Accent color commit3d0f385af7Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:38:42 2023 +0100 [CHANGE] Overhaul of the AppDetailView with version history, reviews & ratings, and app information commitf3e58e1485Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:37:37 2023 +0100 [UPDATE] AppPillButton dimensions and expiration text commitd3e04c1db7Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:35:09 2023 +0100 [FIX] Show App IDs button only if user is logged in with their Apple ID commited1970245aAuthor: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:32:11 2023 +0100 [ADD] Load and show trusted sources with option to add them to the app commit15dd885a1bAuthor: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:30:21 2023 +0100 [ADD] Credits section in SettingsView commit4663c01700Author: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 21:23:16 2023 +0100 [CHANGE] Extracted all strings into the Localizable.strings commite733601c66Author: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 19:03:33 2023 +0100 [FIX] Text alignment in SettingsView commitfc974a8079Author: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 19:02:58 2023 +0100 [ADD] Hint for new users who don't have any sources commit6aaadc79e5Author: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 18:59:39 2023 +0100 [ADD] AppScreenshot view with ImageProcessor to automatically rotate landscape screenshots commitb9177e89c6Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 13:37:38 2023 +0100 [FIX] Issues introduced by changes to the AltSource specification. commit1531c0a77fAuthor: Fabian Thies <github@fabian-thies.de> Date: Fri Jan 13 12:48:27 2023 +0100 [UPDATE] Translations (#7) This PR merges all the new translations made on the SideStore weblate instance (https://translate.sidestore.io/projects/sidestore/app). New translations: - French - Korean Updated translations: - Spanish Co-authored-by: bogotesr <bogotesr@gmail.com> Co-authored-by: GABO1423 <35014183+GABO1423@users.noreply.github.com> Co-authored-by: Joss Laymon <71040782+bogotesr@users.noreply.github.com> Co-authored-by: mindfreakdev <shost212@gmail.com> Co-authored-by: Python <rjp2030@proton.me> Co-authored-by: Testi Cules <ervd516@gmail.com> commit1dde36faceAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:25:50 2023 +0100 [FIX] Changes made by Xcode 14 after building the app commitc3c3783ba4Author: Upal <shost212@gmail.com> Date: Mon Dec 26 19:18:33 2022 +0530 Added Hindi Language (#5) * Added Hindi Language commit8400af3423Author: mindfreakdev <shost212@gmail.com> Date: Sun Dec 25 16:52:01 2022 +0530 Added Dutch Language commit243c7efc09Author: mindfreakdev <shost212@gmail.com> Date: Sun Dec 25 12:30:42 2022 +0530 Added Ukrainian Language commit0298a0235bAuthor: mindfreakdev <shost212@gmail.com> Date: Sun Dec 25 12:28:00 2022 +0530 Added Ukrainian Language commite5b2496b09Author: Gabriel Morazán <35014183+GABO1423@users.noreply.github.com> Date: Sun Dec 25 01:08:47 2022 -0400 Screen Crunch sucks Signed-off-by: Gabriel Morazán <35014183+GABO1423@users.noreply.github.com> commit75c52a3af2Author: GABO1423 <35014183+GABO1423@users.noreply.github.com> Date: Sun Dec 25 00:58:22 2022 -0400 Spanish Translation Tweaks commit2c07009b04Author: bogotesr <bogotesr@gmail.com> Date: Sat Dec 24 21:06:28 2022 -0700 Add es-419 and finish adding support for the translations Added Latin American Spanish (probably not the best translation) Made everything reference the swiftgen stuff rather than having strings commit6257fdcd61Author: Fabian Thies <git@fabian-thies.de> Date: Thu Dec 22 10:29:57 2022 +0100 [CHANGE] Extracted some example strings and replaced them by generated localized strings commite23956d4edAuthor: Fabian Thies <git@fabian-thies.de> Date: Thu Dec 22 10:21:57 2022 +0100 [ADD] SwiftGen configuration and generated files commit1341de8315Author: Fabian Thies <git@fabian-thies.de> Date: Thu Dec 22 10:10:58 2022 +0100 [ADD] Empty Localizable.strings commit77f5844e4dAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:04:10 2023 +0100 [WIP] AppScreenshot view with ImageProcessor to automatically rotate landscape images. Possible through my fork of the AsyncImage framework. commitb3c4819e8dAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:02:56 2023 +0100 [WIP] Fetch trusted sources in SourcesView commita6ca73f8fcAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:02:06 2023 +0100 [WIP] AppIDs view in My Apps section commitf17d00c0bcAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:00:00 2023 +0100 [ADD] Badge in AppDetailView for apps from the official source and (WIP) trusted sources commit875453533bAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 11:58:25 2023 +0100 [ADD] Hint view in MyAppsView telling the user about where to find updates in the future if no updates are available commit9a7a39a58eAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 11:54:44 2023 +0100 [FIX] App permission icon color commit65db392388Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 11:51:06 2023 +0100 [ADD] Show source name and external url domain in NewsItemView commit6a6fc22995Author: Fabian Thies <git@fabian-thies.de> Date: Fri Dec 23 16:02:57 2022 +0100 [ADD] Full-screen app screenshot preview commit5697c4c063Author: Fabian Thies <git@fabian-thies.de> Date: Fri Dec 23 15:21:16 2022 +0100 [CHANGE] Replace system image name strings with SFSymbols commitbcd54067d3Author: Fabian Thies <git@fabian-thies.de> Date: Fri Dec 23 13:12:39 2022 +0100 [ADD] Dependency: SFSafeSymbols commitc7ce32a562Author: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:49:49 2022 +0100 [ADD] WIP: Promoted category cards and app list filter button in BrowseView commit5a1496a3cdAuthor: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:48:45 2022 +0100 [FIX] AccentColor in dark mode commit497c048240Author: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:48:23 2022 +0100 [ADD] Carousel for SideStore-specific announcements in NewsView commit02e48a207fAuthor: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:45:44 2022 +0100 [ADD] WIP: Add My Apps view with support for sideloading new apps, refreshing installed apps and much more commita0eb30f98eAuthor: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:20:54 2022 +0100 [CHANGE] Fixed the AppRowView background blur effect commit378631e976Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:20:10 2022 +0100 [ADD] Backported dismiss() environment variable to let views dismiss themselves commit0e7083539dAuthor: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:18:57 2022 +0100 [ADD] Search bar for BrowseView on iOS 15 commit0c034b61d9Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:16:36 2022 +0100 [CHANGE] Fetch news when NewsView appears commit89dea75b84Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:15:16 2022 +0100 Improved app detail view commit81ea791b63Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:12:38 2022 +0100 [ADD] Authentication view for connecting SideStore to an Apple ID commitc81f716427Author: Fabian Thies <git@fabian-thies.de> Date: Sun Nov 27 16:41:30 2022 +0100 [WIP] Fixed the app permissions grid in AppDetailView commiteb151d74ddAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Nov 27 16:17:08 2022 +0100 [ADD] Expandable app and version description texts commit0dc7af5e51Author: Fabian Thies <git@fabian-thies.de> Date: Sun Nov 27 00:26:15 2022 +0100 [ADD] iOS 13 compatible AsyncImage implementation with cache commitd3e8473f45Author: Fabian Thies <git@fabian-thies.de> Date: Wed Nov 23 22:34:02 2022 +0100 [ADD] News, Browse and Settings views ported to SwiftUI This commit contains WIP SwiftUI versions of most of the views in SideStore. commit38a1c7eef6Author: Fabian Thies <git@fabian-thies.de> Date: Sat May 20 20:05:36 2023 +0200 Fix rebase issues commitf6252c3a8bAuthor: Fabian Thies <git@fabian-thies.de> Date: Sat May 20 19:10:51 2023 +0200 Fix trusted sources being enabled in onboarding process regardless of user choice commit653d80b88eAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri May 19 13:14:15 2023 +0200 Add onboarding screens for an easy setup of SideStore commit89609ad35cAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 14:31:01 2023 +0100 [ADD] UI for writing an app review and submit an app rating commit2211013e57Author: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 14:30:21 2023 +0100 [CHANGE] UI fixes and SwiftUI previews for easier development commitf206ee1406Author: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 14:25:13 2023 +0100 [ADD] Refresh all apps functionality in MyAppsView commit00dc9b36afAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Feb 19 11:40:26 2023 +0100 [FIX] STDOUT output not visible in Xcode console commit24146cef90Author: Fabian Thies <git@fabian-thies.de> Date: Mon Feb 13 18:56:34 2023 +0100 [ADD] LocalConsole showing STDOUT and STDERR commitc46a50ec58Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 14:35:58 2023 +0100 [FIX] App compatibility info commitde7e909c01Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 14:29:02 2023 +0100 [ADD] Debug entries for refresh attempts, sending feedback, advanced settings, and resetting the pairing file commitfbc754d8b7Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 13:07:04 2023 +0100 [ADD] Error log view commit767d878051Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 12:55:25 2023 +0100 [FIX] Various UI issues commit132b140af2Author: Fabian Thies <git@fabian-thies.de> Date: Sat Feb 4 12:46:43 2023 +0100 [ADD] App report button and trusted source badge in app detail view commitdf7d8871ffAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Feb 3 18:19:07 2023 +0100 [FIX] AppIDsView and authentication workflow commitca2398e4c7Author: Fabian Thies <git@fabian-thies.de> Date: Fri Feb 3 18:16:48 2023 +0100 [FIX] Full screen app screenshot previews commitb8f02d2152Author: Fabian Thies <git@fabian-thies.de> Date: Fri Feb 3 14:58:06 2023 +0100 [FIX] Accent color commite85876cd24Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:38:42 2023 +0100 [CHANGE] Overhaul of the AppDetailView with version history, reviews & ratings, and app information commit3f06a53058Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:37:37 2023 +0100 [UPDATE] AppPillButton dimensions and expiration text commit4ee053a4f9Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:35:09 2023 +0100 [FIX] Show App IDs button only if user is logged in with their Apple ID commite5369524ceAuthor: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:32:11 2023 +0100 [ADD] Load and show trusted sources with option to add them to the app commit77465cebd0Author: Fabian Thies <git@fabian-thies.de> Date: Tue Jan 31 22:30:21 2023 +0100 [ADD] Credits section in SettingsView commitf90bf3bfcfAuthor: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 21:23:16 2023 +0100 [CHANGE] Extracted all strings into the Localizable.strings commit0000610b9dAuthor: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 19:03:33 2023 +0100 [FIX] Text alignment in SettingsView commitc7e095583dAuthor: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 19:02:58 2023 +0100 [ADD] Hint for new users who don't have any sources commita725f3e9ccAuthor: Fabian Thies <git@fabian-thies.de> Date: Mon Jan 16 18:59:39 2023 +0100 [ADD] AppScreenshot view with ImageProcessor to automatically rotate landscape screenshots commitb5dea18073Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 13:37:38 2023 +0100 [FIX] Issues introduced by changes to the AltSource specification. commitb9b309e603Author: Fabian Thies <github@fabian-thies.de> Date: Fri Jan 13 12:48:27 2023 +0100 [UPDATE] Translations (#7) This PR merges all the new translations made on the SideStore weblate instance (https://translate.sidestore.io/projects/sidestore/app). New translations: - French - Korean Updated translations: - Spanish Co-authored-by: bogotesr <bogotesr@gmail.com> Co-authored-by: GABO1423 <35014183+GABO1423@users.noreply.github.com> Co-authored-by: Joss Laymon <71040782+bogotesr@users.noreply.github.com> Co-authored-by: mindfreakdev <shost212@gmail.com> Co-authored-by: Python <rjp2030@proton.me> Co-authored-by: Testi Cules <ervd516@gmail.com> commit15f1be0aa8Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:25:50 2023 +0100 [FIX] Changes made by Xcode 14 after building the app commitffd80ce0b4Author: Upal <shost212@gmail.com> Date: Mon Dec 26 19:18:33 2022 +0530 Added Hindi Language (#5) * Added Hindi Language commit350891ee2aAuthor: mindfreakdev <shost212@gmail.com> Date: Sun Dec 25 16:52:01 2022 +0530 Added Dutch Language commit5dec1cd561Author: mindfreakdev <shost212@gmail.com> Date: Sun Dec 25 12:30:42 2022 +0530 Added Ukrainian Language commitc4d235d742Author: mindfreakdev <shost212@gmail.com> Date: Sun Dec 25 12:28:00 2022 +0530 Added Ukrainian Language commitcdc6675dd5Author: Gabriel Morazán <35014183+GABO1423@users.noreply.github.com> Date: Sun Dec 25 01:08:47 2022 -0400 Screen Crunch sucks Signed-off-by: Gabriel Morazán <35014183+GABO1423@users.noreply.github.com> commit85635bb26eAuthor: GABO1423 <35014183+GABO1423@users.noreply.github.com> Date: Sun Dec 25 00:58:22 2022 -0400 Spanish Translation Tweaks commit3be0a4a89cAuthor: bogotesr <bogotesr@gmail.com> Date: Sat Dec 24 21:06:28 2022 -0700 Add es-419 and finish adding support for the translations Added Latin American Spanish (probably not the best translation) Made everything reference the swiftgen stuff rather than having strings commit47e47fb3cfAuthor: Fabian Thies <git@fabian-thies.de> Date: Thu Dec 22 10:29:57 2022 +0100 [CHANGE] Extracted some example strings and replaced them by generated localized strings commit48903034b6Author: Fabian Thies <git@fabian-thies.de> Date: Thu Dec 22 10:21:57 2022 +0100 [ADD] SwiftGen configuration and generated files commit6952218ee7Author: Fabian Thies <git@fabian-thies.de> Date: Thu Dec 22 10:10:58 2022 +0100 [ADD] Empty Localizable.strings commit80146c1e03Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:04:10 2023 +0100 [WIP] AppScreenshot view with ImageProcessor to automatically rotate landscape images. Possible through my fork of the AsyncImage framework. commit642ae996c9Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:02:56 2023 +0100 [WIP] Fetch trusted sources in SourcesView commit8040636aa5Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:02:06 2023 +0100 [WIP] AppIDs view in My Apps section commit731fcfaca7Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 12:00:00 2023 +0100 [ADD] Badge in AppDetailView for apps from the official source and (WIP) trusted sources commit708fb3fccdAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 11:58:25 2023 +0100 [ADD] Hint view in MyAppsView telling the user about where to find updates in the future if no updates are available commit9f429fb068Author: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 11:54:44 2023 +0100 [FIX] App permission icon color commit29fc693f4dAuthor: Fabian Thies <git@fabian-thies.de> Date: Fri Jan 13 11:51:06 2023 +0100 [ADD] Show source name and external url domain in NewsItemView commit6f373ad305Author: Fabian Thies <git@fabian-thies.de> Date: Fri Dec 23 16:02:57 2022 +0100 [ADD] Full-screen app screenshot preview commitc069d779d9Author: Fabian Thies <git@fabian-thies.de> Date: Fri Dec 23 15:21:16 2022 +0100 [CHANGE] Replace system image name strings with SFSymbols commitcd88970a22Author: Fabian Thies <git@fabian-thies.de> Date: Fri Dec 23 13:12:39 2022 +0100 [ADD] Dependency: SFSafeSymbols commit6b6708e43cAuthor: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:49:49 2022 +0100 [ADD] WIP: Promoted category cards and app list filter button in BrowseView commit9206eeb9e3Author: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:48:45 2022 +0100 [FIX] AccentColor in dark mode commit080bbb3c51Author: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:48:23 2022 +0100 [ADD] Carousel for SideStore-specific announcements in NewsView commitea2c862900Author: Fabian Thies <git@fabian-thies.de> Date: Wed Dec 21 17:45:44 2022 +0100 [ADD] WIP: Add My Apps view with support for sideloading new apps, refreshing installed apps and much more commit4fe72ea113Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:20:54 2022 +0100 [CHANGE] Fixed the AppRowView background blur effect commitc486a62b50Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:20:10 2022 +0100 [ADD] Backported dismiss() environment variable to let views dismiss themselves commit3ce4451da4Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:18:57 2022 +0100 [ADD] Search bar for BrowseView on iOS 15 commit294ba12391Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:16:36 2022 +0100 [CHANGE] Fetch news when NewsView appears commit4a3343fe61Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:15:16 2022 +0100 Improved app detail view commitd1e6ddd435Author: Fabian Thies <git@fabian-thies.de> Date: Mon Dec 12 19:12:38 2022 +0100 [ADD] Authentication view for connecting SideStore to an Apple ID commit3e0379dc70Author: Fabian Thies <git@fabian-thies.de> Date: Sun Nov 27 16:41:30 2022 +0100 [WIP] Fixed the app permissions grid in AppDetailView commitd99674f8bdAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Nov 27 16:17:08 2022 +0100 [ADD] Expandable app and version description texts commitca7acc17daAuthor: Fabian Thies <git@fabian-thies.de> Date: Sun Nov 27 00:26:15 2022 +0100 [ADD] iOS 13 compatible AsyncImage implementation with cache commit16a8bce102Author: Fabian Thies <git@fabian-thies.de> Date: Wed Nov 23 22:34:02 2022 +0100 [ADD] News, Browse and Settings views ported to SwiftUI This commit contains WIP SwiftUI versions of most of the views in SideStore.
18
AltStore/App/SideStoreUIApp.swift
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// SideStoreUIApp.swift
|
||||
// SideStoreUI
|
||||
//
|
||||
// Created by Fabian Thies on 18.11.22.
|
||||
// Copyright © 2022 Fabian Thies. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct SideStoreUIApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
RootView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import UIKit
|
||||
import UserNotifications
|
||||
import AVFoundation
|
||||
import Intents
|
||||
import LocalConsole
|
||||
|
||||
import AltStoreCore
|
||||
import AltSign
|
||||
@@ -58,11 +59,17 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
|
||||
{
|
||||
// Copy STDOUT and STDERR to the logging console
|
||||
_ = OutputCapturer.shared
|
||||
|
||||
// Register default settings before doing anything else.
|
||||
UserDefaults.registerDefaults()
|
||||
|
||||
UnstableFeatures.load()
|
||||
|
||||
LCManager.shared.isVisible = UserDefaults.standard.isConsoleEnabled
|
||||
LCManager.shared.isCharacterLimitDisabled = true // we want all logs exported
|
||||
|
||||
DatabaseManager.shared.start { (error) in
|
||||
if let error = error
|
||||
{
|
||||
|
||||
19
AltStore/Extensions/Source+Trusted.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Source+Trusted.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 04.02.23.
|
||||
// Copyright © 2023 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import AltStoreCore
|
||||
|
||||
extension Source {
|
||||
var isOfficial: Bool {
|
||||
self.identifier == Source.altStoreIdentifier
|
||||
}
|
||||
|
||||
var isTrusted: Bool {
|
||||
UserDefaults.shared.trustedSourceIDs?.contains(self.identifier) ?? false
|
||||
}
|
||||
}
|
||||
17
AltStore/Extensions/StoreApp+Filterable.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// StoreApp+Searchable.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 01.12.22.
|
||||
// Copyright © 2022 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import AltStoreCore
|
||||
|
||||
extension StoreApp: Filterable {
|
||||
func matches(_ searchText: String) -> Bool {
|
||||
searchText.isEmpty ||
|
||||
self.name.lowercased().contains(searchText.lowercased()) ||
|
||||
self.developerName.lowercased().contains(searchText.lowercased())
|
||||
}
|
||||
}
|
||||
15
AltStore/Extensions/StoreApp+SideStore.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// StoreApp+SideStore.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by naturecodevoid on 4/9/23.
|
||||
// Copyright © 2023 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import AltStoreCore
|
||||
|
||||
extension StoreApp {
|
||||
var isSideStore: Bool {
|
||||
self.bundleIdentifier == Bundle.Info.appbundleIdentifier
|
||||
}
|
||||
}
|
||||
19
AltStore/Extensions/StoreApp+Trusted.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// StoreApp+Trusted.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 04.02.23.
|
||||
// Copyright © 2023 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import AltStoreCore
|
||||
|
||||
extension StoreApp {
|
||||
var isFromOfficialSource: Bool {
|
||||
self.source?.isOfficial ?? false
|
||||
}
|
||||
|
||||
var isFromTrustedSource: Bool {
|
||||
self.source?.isTrusted ?? false
|
||||
}
|
||||
}
|
||||
22
AltStore/Extensions/View+Hidden.swift
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// View+Hidden.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by naturecodevoid on 2/18/23.
|
||||
// Copyright © 2023 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// https://stackoverflow.com/a/59228385 (modified)
|
||||
extension View {
|
||||
@ViewBuilder func isHidden(_ hidden: Binding<Bool>, remove: Bool = false) -> some View {
|
||||
if hidden.wrappedValue {
|
||||
if !remove {
|
||||
self.hidden()
|
||||
}
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
207
AltStore/Generated/Assets.swift
Normal file
@@ -0,0 +1,207 @@
|
||||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
#if os(macOS)
|
||||
import AppKit
|
||||
#elseif os(iOS)
|
||||
import UIKit
|
||||
#elseif os(tvOS) || os(watchOS)
|
||||
import UIKit
|
||||
#endif
|
||||
#if canImport(SwiftUI)
|
||||
import SwiftUI
|
||||
#endif
|
||||
|
||||
// Deprecated typealiases
|
||||
@available(*, deprecated, renamed: "ColorAsset.Color", message: "This typealias will be removed in SwiftGen 7.0")
|
||||
internal typealias AssetColorTypeAlias = ColorAsset.Color
|
||||
@available(*, deprecated, renamed: "ImageAsset.Image", message: "This typealias will be removed in SwiftGen 7.0")
|
||||
internal typealias AssetImageTypeAlias = ImageAsset.Image
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length implicit_return
|
||||
|
||||
// MARK: - Asset Catalogs
|
||||
|
||||
// swiftlint:disable identifier_name line_length nesting type_body_length type_name
|
||||
internal enum Asset {
|
||||
internal static let back = ImageAsset(name: "Back")
|
||||
internal static let betaBadge = ImageAsset(name: "BetaBadge")
|
||||
internal static let accentColor = ColorAsset(name: "AccentColor")
|
||||
internal static let background = ColorAsset(name: "Background")
|
||||
internal static let blurTint = ColorAsset(name: "BlurTint")
|
||||
internal static let settingsBackground = ColorAsset(name: "SettingsBackground")
|
||||
internal static let settingsHighlighted = ColorAsset(name: "SettingsHighlighted")
|
||||
internal static let honeydewImage = ImageAsset(name: "Honeydew-image")
|
||||
internal static let midnightImage = ImageAsset(name: "Midnight-image")
|
||||
internal static let neonImage = ImageAsset(name: "Neon-image")
|
||||
internal static let next = ImageAsset(name: "Next")
|
||||
internal static let skyImage = ImageAsset(name: "Sky-image")
|
||||
internal static let starburstImage = ImageAsset(name: "Starburst-image")
|
||||
internal static let steelImage = ImageAsset(name: "Steel-image")
|
||||
internal static let stormImage = ImageAsset(name: "Storm-image")
|
||||
internal static let browse = ImageAsset(name: "Browse")
|
||||
internal static let myApps = ImageAsset(name: "MyApps")
|
||||
internal static let news = ImageAsset(name: "News")
|
||||
internal static let settings = ImageAsset(name: "Settings")
|
||||
internal static let vistaImage = ImageAsset(name: "Vista-image")
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length nesting type_body_length type_name
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
internal final class ColorAsset {
|
||||
internal fileprivate(set) var name: String
|
||||
|
||||
#if os(macOS)
|
||||
internal typealias Color = NSColor
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
internal typealias Color = UIColor
|
||||
#endif
|
||||
|
||||
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *)
|
||||
internal private(set) lazy var color: Color = {
|
||||
guard let color = Color(asset: self) else {
|
||||
fatalError("Unable to load color asset named \(name).")
|
||||
}
|
||||
return color
|
||||
}()
|
||||
|
||||
#if os(iOS) || os(tvOS)
|
||||
@available(iOS 11.0, tvOS 11.0, *)
|
||||
internal func color(compatibleWith traitCollection: UITraitCollection) -> Color {
|
||||
let bundle = BundleToken.bundle
|
||||
guard let color = Color(named: name, in: bundle, compatibleWith: traitCollection) else {
|
||||
fatalError("Unable to load color asset named \(name).")
|
||||
}
|
||||
return color
|
||||
}
|
||||
#endif
|
||||
|
||||
#if canImport(SwiftUI)
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
internal private(set) lazy var swiftUIColor: SwiftUI.Color = {
|
||||
SwiftUI.Color(asset: self)
|
||||
}()
|
||||
#endif
|
||||
|
||||
fileprivate init(name: String) {
|
||||
self.name = name
|
||||
}
|
||||
}
|
||||
|
||||
internal extension ColorAsset.Color {
|
||||
@available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *)
|
||||
convenience init?(asset: ColorAsset) {
|
||||
let bundle = BundleToken.bundle
|
||||
#if os(iOS) || os(tvOS)
|
||||
self.init(named: asset.name, in: bundle, compatibleWith: nil)
|
||||
#elseif os(macOS)
|
||||
self.init(named: NSColor.Name(asset.name), bundle: bundle)
|
||||
#elseif os(watchOS)
|
||||
self.init(named: asset.name)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(SwiftUI)
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
internal extension SwiftUI.Color {
|
||||
init(asset: ColorAsset) {
|
||||
let bundle = BundleToken.bundle
|
||||
self.init(asset.name, bundle: bundle)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal struct ImageAsset {
|
||||
internal fileprivate(set) var name: String
|
||||
|
||||
#if os(macOS)
|
||||
internal typealias Image = NSImage
|
||||
#elseif os(iOS) || os(tvOS) || os(watchOS)
|
||||
internal typealias Image = UIImage
|
||||
#endif
|
||||
|
||||
@available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.7, *)
|
||||
internal var image: Image {
|
||||
let bundle = BundleToken.bundle
|
||||
#if os(iOS) || os(tvOS)
|
||||
let image = Image(named: name, in: bundle, compatibleWith: nil)
|
||||
#elseif os(macOS)
|
||||
let name = NSImage.Name(self.name)
|
||||
let image = (bundle == .main) ? NSImage(named: name) : bundle.image(forResource: name)
|
||||
#elseif os(watchOS)
|
||||
let image = Image(named: name)
|
||||
#endif
|
||||
guard let result = image else {
|
||||
fatalError("Unable to load image asset named \(name).")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
#if os(iOS) || os(tvOS)
|
||||
@available(iOS 8.0, tvOS 9.0, *)
|
||||
internal func image(compatibleWith traitCollection: UITraitCollection) -> Image {
|
||||
let bundle = BundleToken.bundle
|
||||
guard let result = Image(named: name, in: bundle, compatibleWith: traitCollection) else {
|
||||
fatalError("Unable to load image asset named \(name).")
|
||||
}
|
||||
return result
|
||||
}
|
||||
#endif
|
||||
|
||||
#if canImport(SwiftUI)
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
internal var swiftUIImage: SwiftUI.Image {
|
||||
SwiftUI.Image(asset: self)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal extension ImageAsset.Image {
|
||||
@available(iOS 8.0, tvOS 9.0, watchOS 2.0, *)
|
||||
@available(macOS, deprecated,
|
||||
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
|
||||
convenience init?(asset: ImageAsset) {
|
||||
#if os(iOS) || os(tvOS)
|
||||
let bundle = BundleToken.bundle
|
||||
self.init(named: asset.name, in: bundle, compatibleWith: nil)
|
||||
#elseif os(macOS)
|
||||
self.init(named: NSImage.Name(asset.name))
|
||||
#elseif os(watchOS)
|
||||
self.init(named: asset.name)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(SwiftUI)
|
||||
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
|
||||
internal extension SwiftUI.Image {
|
||||
init(asset: ImageAsset) {
|
||||
let bundle = BundleToken.bundle
|
||||
self.init(asset.name, bundle: bundle)
|
||||
}
|
||||
|
||||
init(asset: ImageAsset, label: Text) {
|
||||
let bundle = BundleToken.bundle
|
||||
self.init(asset.name, bundle: bundle, label: label)
|
||||
}
|
||||
|
||||
init(decorative asset: ImageAsset) {
|
||||
let bundle = BundleToken.bundle
|
||||
self.init(decorative: asset.name, bundle: bundle)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
431
AltStore/Generated/Localizations.swift
Normal file
@@ -0,0 +1,431 @@
|
||||
// swiftlint:disable all
|
||||
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
|
||||
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command file_length implicit_return prefer_self_in_static_references
|
||||
|
||||
// MARK: - Strings
|
||||
|
||||
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
|
||||
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
internal enum L10n {
|
||||
internal enum Action {
|
||||
/// Cancel
|
||||
internal static let cancel = L10n.tr("Localizable", "Action.cancel", fallback: "Cancel")
|
||||
/// Close
|
||||
internal static let close = L10n.tr("Localizable", "Action.close", fallback: "Close")
|
||||
/// General Actions
|
||||
internal static let done = L10n.tr("Localizable", "Action.done", fallback: "Done")
|
||||
/// Enable
|
||||
internal static let enable = L10n.tr("Localizable", "Action.enable", fallback: "Enable")
|
||||
/// Submit
|
||||
internal static let submit = L10n.tr("Localizable", "Action.submit", fallback: "Submit")
|
||||
/// Try Again
|
||||
internal static let tryAgain = L10n.tr("Localizable", "Action.tryAgain", fallback: "Try Again")
|
||||
}
|
||||
internal enum AddSourceView {
|
||||
/// Continue
|
||||
internal static let `continue` = L10n.tr("Localizable", "AddSourceView.continue", fallback: "Continue")
|
||||
/// AddSourceView
|
||||
internal static let sourceURL = L10n.tr("Localizable", "AddSourceView.sourceURL", fallback: "Source URL")
|
||||
/// Please enter the source url here. Then, tap continue to validate and add the source in the next step.
|
||||
internal static let sourceWarning = L10n.tr("Localizable", "AddSourceView.sourceWarning", fallback: "Please enter the source url here. Then, tap continue to validate and add the source in the next step.")
|
||||
/// Be careful with unvalidated third-party sources! Make sure to only add sources that you trust.
|
||||
internal static let sourceWarningContinued = L10n.tr("Localizable", "AddSourceView.sourceWarningContinued", fallback: "Be careful with unvalidated third-party sources! Make sure to only add sources that you trust.")
|
||||
/// Add Source
|
||||
internal static let title = L10n.tr("Localizable", "AddSourceView.title", fallback: "Add Source")
|
||||
}
|
||||
internal enum AdvancedSettingsView {
|
||||
/// Anisette Server
|
||||
internal static let anisette = L10n.tr("Localizable", "AdvancedSettingsView.anisette", fallback: "Anisette Server")
|
||||
/// Danger Zone
|
||||
internal static let dangerZone = L10n.tr("Localizable", "AdvancedSettingsView.dangerZone", fallback: "Danger Zone")
|
||||
/// If you disable "Use preferred servers" then SideStore will use the server you input into the "Anisette URL" box rather than one selected in "Anisette Server".
|
||||
internal static let dangerZoneInfo = L10n.tr("Localizable", "AdvancedSettingsView.dangerZoneInfo", fallback: "If you disable \"Use preferred servers\" then SideStore will use the server you input into the \"Anisette URL\" box rather than one selected in \"Anisette Server\".")
|
||||
/// AdvancedSettingsView
|
||||
internal static let title = L10n.tr("Localizable", "AdvancedSettingsView.title", fallback: "Advanced Settings")
|
||||
internal enum DangerZone {
|
||||
/// Anisette URL
|
||||
internal static let anisetteURL = L10n.tr("Localizable", "AdvancedSettingsView.DangerZone.anisetteURL", fallback: "Anisette URL")
|
||||
/// Use preferred servers
|
||||
internal static let usePreferred = L10n.tr("Localizable", "AdvancedSettingsView.DangerZone.usePreferred", fallback: "Use preferred servers")
|
||||
}
|
||||
}
|
||||
internal enum AppAction {
|
||||
/// Activate
|
||||
internal static let activate = L10n.tr("Localizable", "AppAction.activate", fallback: "Activate")
|
||||
/// Backup
|
||||
internal static let backup = L10n.tr("Localizable", "AppAction.backup", fallback: "Backup")
|
||||
/// Customize icon
|
||||
internal static let chooseCustomIcon = L10n.tr("Localizable", "AppAction.chooseCustomIcon", fallback: "Customize icon")
|
||||
/// Deactivate
|
||||
internal static let deactivate = L10n.tr("Localizable", "AppAction.deactivate", fallback: "Deactivate")
|
||||
/// Activate JIT
|
||||
internal static let enableJIT = L10n.tr("Localizable", "AppAction.enableJIT", fallback: "Activate JIT")
|
||||
/// Export backup
|
||||
internal static let exportBackup = L10n.tr("Localizable", "AppAction.exportBackup", fallback: "Export backup")
|
||||
/// AppAction
|
||||
internal static let install = L10n.tr("Localizable", "AppAction.install", fallback: "Install")
|
||||
/// Open
|
||||
internal static let `open` = L10n.tr("Localizable", "AppAction.open", fallback: "Open")
|
||||
/// Refresh
|
||||
internal static let refresh = L10n.tr("Localizable", "AppAction.refresh", fallback: "Refresh")
|
||||
/// Remove
|
||||
internal static let remove = L10n.tr("Localizable", "AppAction.remove", fallback: "Remove")
|
||||
/// Reset icon
|
||||
internal static let resetIcon = L10n.tr("Localizable", "AppAction.resetIcon", fallback: "Reset icon")
|
||||
/// Restore backup
|
||||
internal static let restoreBackup = L10n.tr("Localizable", "AppAction.restoreBackup", fallback: "Restore backup")
|
||||
}
|
||||
internal enum AppDetailView {
|
||||
/// Information
|
||||
internal static let information = L10n.tr("Localizable", "AppDetailView.information", fallback: "Information")
|
||||
/// More...
|
||||
internal static let more = L10n.tr("Localizable", "AppDetailView.more", fallback: "More...")
|
||||
/// The app requires no permissions.
|
||||
internal static let noPermissions = L10n.tr("Localizable", "AppDetailView.noPermissions", fallback: "The app requires no permissions.")
|
||||
/// No screenshots available for this app.
|
||||
internal static let noScreenshots = L10n.tr("Localizable", "AppDetailView.noScreenshots", fallback: "No screenshots available for this app.")
|
||||
/// No version information
|
||||
internal static let noVersionInformation = L10n.tr("Localizable", "AppDetailView.noVersionInformation", fallback: "No version information")
|
||||
/// Permissions
|
||||
internal static let permissions = L10n.tr("Localizable", "AppDetailView.permissions", fallback: "Permissions")
|
||||
/// Ratings & Reviews
|
||||
internal static let reviews = L10n.tr("Localizable", "AppDetailView.reviews", fallback: "Ratings & Reviews")
|
||||
/// Version %@
|
||||
internal static func version(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "AppDetailView.version", String(describing: p1), fallback: "Version %@")
|
||||
}
|
||||
/// What's New
|
||||
internal static let whatsNew = L10n.tr("Localizable", "AppDetailView.whatsNew", fallback: "What's New")
|
||||
internal enum Badge {
|
||||
/// AppDetailView
|
||||
internal static let official = L10n.tr("Localizable", "AppDetailView.Badge.official", fallback: "Official App")
|
||||
/// From Trusted Source
|
||||
internal static let trusted = L10n.tr("Localizable", "AppDetailView.Badge.trusted", fallback: "From Trusted Source")
|
||||
}
|
||||
internal enum Information {
|
||||
/// Compatibility
|
||||
internal static let compatibility = L10n.tr("Localizable", "AppDetailView.Information.compatibility", fallback: "Compatibility")
|
||||
/// Requires iOS %@ or higher
|
||||
internal static func compatibilityAtLeast(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "AppDetailView.Information.compatibilityAtLeast", String(describing: p1), fallback: "Requires iOS %@ or higher")
|
||||
}
|
||||
/// Unknown
|
||||
internal static let compatibilityCompatible = L10n.tr("Localizable", "AppDetailView.Information.compatibilityCompatible", fallback: "Unknown")
|
||||
/// Requires iOS %@ or lower
|
||||
internal static func compatibilityOrLower(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "AppDetailView.Information.compatibilityOrLower", String(describing: p1), fallback: "Requires iOS %@ or lower")
|
||||
}
|
||||
/// Unknown
|
||||
internal static let compatibilityUnknown = L10n.tr("Localizable", "AppDetailView.Information.compatibilityUnknown", fallback: "Unknown")
|
||||
/// Developer
|
||||
internal static let developer = L10n.tr("Localizable", "AppDetailView.Information.developer", fallback: "Developer")
|
||||
/// Latest Version
|
||||
internal static let latestVersion = L10n.tr("Localizable", "AppDetailView.Information.latestVersion", fallback: "Latest Version")
|
||||
/// Size
|
||||
internal static let size = L10n.tr("Localizable", "AppDetailView.Information.size", fallback: "Size")
|
||||
/// Source
|
||||
internal static let source = L10n.tr("Localizable", "AppDetailView.Information.source", fallback: "Source")
|
||||
}
|
||||
internal enum Reviews {
|
||||
/// out of %d
|
||||
internal static func outOf(_ p1: Int) -> String {
|
||||
return L10n.tr("Localizable", "AppDetailView.Reviews.outOf", p1, fallback: "out of %d")
|
||||
}
|
||||
/// %d Ratings
|
||||
internal static func ratings(_ p1: Int) -> String {
|
||||
return L10n.tr("Localizable", "AppDetailView.Reviews.ratings", p1, fallback: "%d Ratings")
|
||||
}
|
||||
/// See All
|
||||
internal static let seeAll = L10n.tr("Localizable", "AppDetailView.Reviews.seeAll", fallback: "See All")
|
||||
}
|
||||
internal enum WhatsNew {
|
||||
/// Show project on GitHub
|
||||
internal static let showOnGithub = L10n.tr("Localizable", "AppDetailView.WhatsNew.showOnGithub", fallback: "Show project on GitHub")
|
||||
/// Version History
|
||||
internal static let versionHistory = L10n.tr("Localizable", "AppDetailView.WhatsNew.versionHistory", fallback: "Version History")
|
||||
}
|
||||
}
|
||||
internal enum AppIDsView {
|
||||
/// Each app and app extension installed with SideStore must register an App ID with Apple.
|
||||
///
|
||||
/// App IDs for paid developer accounts never expire, and there is no limit to how many you can create.
|
||||
internal static let description = L10n.tr("Localizable", "AppIDsView.description", fallback: "Each app and app extension installed with SideStore must register an App ID with Apple.\n\nApp IDs for paid developer accounts never expire, and there is no limit to how many you can create.")
|
||||
/// AppIDsView
|
||||
internal static let title = L10n.tr("Localizable", "AppIDsView.title", fallback: "App IDs")
|
||||
}
|
||||
internal enum AppIconsView {
|
||||
/// AppIconsView
|
||||
internal static let title = L10n.tr("Localizable", "AppIconsView.title", fallback: "App Icon")
|
||||
}
|
||||
internal enum AppPermissionGrid {
|
||||
/// AppPermissionGrid
|
||||
internal static let usageDescription = L10n.tr("Localizable", "AppPermissionGrid.usageDescription", fallback: "Usage Description")
|
||||
}
|
||||
internal enum AppPillButton {
|
||||
/// AppPillButton
|
||||
internal static let free = L10n.tr("Localizable", "AppPillButton.free", fallback: "Free")
|
||||
/// Open
|
||||
internal static let `open` = L10n.tr("Localizable", "AppPillButton.open", fallback: "Open")
|
||||
}
|
||||
internal enum AppRowView {
|
||||
/// AppRowView
|
||||
internal static let sideloaded = L10n.tr("Localizable", "AppRowView.sideloaded", fallback: "Sideloaded")
|
||||
}
|
||||
internal enum AsyncFallibleButton {
|
||||
/// AsyncFallibleButton
|
||||
internal static let error = L10n.tr("Localizable", "AsyncFallibleButton.error", fallback: "An error occurred")
|
||||
}
|
||||
internal enum BrowseView {
|
||||
/// Search
|
||||
internal static let search = L10n.tr("Localizable", "BrowseView.search", fallback: "Search")
|
||||
/// BrowseView
|
||||
internal static let title = L10n.tr("Localizable", "BrowseView.title", fallback: "Browse")
|
||||
internal enum Actions {
|
||||
/// Sources
|
||||
internal static let sources = L10n.tr("Localizable", "BrowseView.Actions.sources", fallback: "Sources")
|
||||
}
|
||||
internal enum Categories {
|
||||
/// Games and
|
||||
/// Emulators
|
||||
internal static let gamesAndEmulators = L10n.tr("Localizable", "BrowseView.Categories.gamesAndEmulators", fallback: "Games and\nEmulators")
|
||||
}
|
||||
internal enum Hints {
|
||||
internal enum NoApps {
|
||||
/// Add Source
|
||||
internal static let addSource = L10n.tr("Localizable", "BrowseView.Hints.NoApps.addSource", fallback: "Add Source")
|
||||
/// Apps are provided by "sources". The specification for them is an open standard, so everyone can create their own source. To get you started, we have compiled a list of "Trusted Sources" which you can check out by tapping the button below.
|
||||
internal static let text = L10n.tr("Localizable", "BrowseView.Hints.NoApps.text", fallback: "Apps are provided by \"sources\". The specification for them is an open standard, so everyone can create their own source. To get you started, we have compiled a list of \"Trusted Sources\" which you can check out by tapping the button below.")
|
||||
/// You don't have any apps yet.
|
||||
internal static let title = L10n.tr("Localizable", "BrowseView.Hints.NoApps.title", fallback: "You don't have any apps yet.")
|
||||
}
|
||||
}
|
||||
internal enum Section {
|
||||
internal enum AllApps {
|
||||
/// All Apps
|
||||
internal static let title = L10n.tr("Localizable", "BrowseView.Section.AllApps.title", fallback: "All Apps")
|
||||
}
|
||||
internal enum PromotedCategories {
|
||||
/// Show all
|
||||
internal static let showAll = L10n.tr("Localizable", "BrowseView.Section.PromotedCategories.showAll", fallback: "Show all")
|
||||
/// Promoted Categories
|
||||
internal static let title = L10n.tr("Localizable", "BrowseView.Section.PromotedCategories.title", fallback: "Promoted Categories")
|
||||
}
|
||||
}
|
||||
}
|
||||
internal enum ConfirmAddSourceView {
|
||||
/// Add Source
|
||||
internal static let addSource = L10n.tr("Localizable", "ConfirmAddSourceView.addSource", fallback: "Add Source")
|
||||
/// ConfirmAddSourceView
|
||||
internal static let apps = L10n.tr("Localizable", "ConfirmAddSourceView.apps", fallback: "Apps")
|
||||
/// News Items
|
||||
internal static let newsItems = L10n.tr("Localizable", "ConfirmAddSourceView.newsItems", fallback: "News Items")
|
||||
/// Source Contents
|
||||
internal static let sourceContents = L10n.tr("Localizable", "ConfirmAddSourceView.sourceContents", fallback: "Source Contents")
|
||||
/// Source Identifier
|
||||
internal static let sourceIdentifier = L10n.tr("Localizable", "ConfirmAddSourceView.sourceIdentifier", fallback: "Source Identifier")
|
||||
/// Source Information
|
||||
internal static let sourceInfo = L10n.tr("Localizable", "ConfirmAddSourceView.sourceInfo", fallback: "Source Information")
|
||||
/// Source URL
|
||||
internal static let sourceURL = L10n.tr("Localizable", "ConfirmAddSourceView.sourceURL", fallback: "Source URL")
|
||||
}
|
||||
internal enum ConnectAppleIDView {
|
||||
/// Apple ID
|
||||
internal static let appleID = L10n.tr("Localizable", "ConnectAppleIDView.appleID", fallback: "Apple ID")
|
||||
/// Cancel
|
||||
internal static let cancel = L10n.tr("Localizable", "ConnectAppleIDView.cancel", fallback: "Cancel")
|
||||
/// Connect Your Apple ID
|
||||
internal static let connectYourAppleID = L10n.tr("Localizable", "ConnectAppleIDView.connectYourAppleID", fallback: "Connect Your Apple ID")
|
||||
/// Failed to Sign In
|
||||
internal static let failedToSignIn = L10n.tr("Localizable", "ConnectAppleIDView.failedToSignIn", fallback: "Failed to Sign In")
|
||||
/// Your Apple ID is used to configure apps so they can be installed on this device. Your credentials will be stored securely in this device's Keychain and sent only to Apple for authentication.
|
||||
internal static let footer = L10n.tr("Localizable", "ConnectAppleIDView.footer", fallback: "Your Apple ID is used to configure apps so they can be installed on this device. Your credentials will be stored securely in this device's Keychain and sent only to Apple for authentication.")
|
||||
/// Password
|
||||
internal static let password = L10n.tr("Localizable", "ConnectAppleIDView.password", fallback: "Password")
|
||||
/// Sign In
|
||||
internal static let signIn = L10n.tr("Localizable", "ConnectAppleIDView.signIn", fallback: "Sign In")
|
||||
/// ConnectAppleIDView
|
||||
internal static let startWithSignIn = L10n.tr("Localizable", "ConnectAppleIDView.startWithSignIn", fallback: "Sign in with your Apple ID to get started.")
|
||||
/// Why do we need this?
|
||||
internal static let whyDoWeNeedThis = L10n.tr("Localizable", "ConnectAppleIDView.whyDoWeNeedThis", fallback: "Why do we need this?")
|
||||
}
|
||||
internal enum DevModeView {
|
||||
/// Console
|
||||
internal static let console = L10n.tr("Localizable", "DevModeView.console", fallback: "Console")
|
||||
/// Data File Explorer
|
||||
internal static let dataExplorer = L10n.tr("Localizable", "DevModeView.dataExplorer", fallback: "Data File Explorer")
|
||||
/// Skip Resign should only be used when you have an IPA that you have self signed. Otherwise, it will break things, and might make SideStore crash (there is absolutely no error handling and everything is expected to work).
|
||||
internal static let footer = L10n.tr("Localizable", "DevModeView.footer", fallback: "Skip Resign should only be used when you have an IPA that you have self signed. Otherwise, it will break things, and might make SideStore crash (there is absolutely no error handling and everything is expected to work).")
|
||||
/// Incorrect password.
|
||||
internal static let incorrectPassword = L10n.tr("Localizable", "DevModeView.incorrectPassword", fallback: "Incorrect password.")
|
||||
/// minimuxer debug actions
|
||||
internal static let minimuxer = L10n.tr("Localizable", "DevModeView.minimuxer", fallback: "minimuxer debug actions")
|
||||
/// Password
|
||||
internal static let password = L10n.tr("Localizable", "DevModeView.password", fallback: "Password")
|
||||
/// SideStore's Developer Mode gives access to a menu with some debugging actions commonly used by developers. **However, some of them can break SideStore if used in the wrong way.**
|
||||
///
|
||||
/// You should only enable Developer Mode if you meet one of the following requirements:
|
||||
/// - You are a SideStore developer or contributor
|
||||
/// - You were asked to do this by a helper when getting support
|
||||
/// - You were asked to do this when you reported a bug or helped a developer test a change
|
||||
///
|
||||
/// **_We will not provide support if you break SideStore with Developer Mode._**
|
||||
internal static let prompt = L10n.tr("Localizable", "DevModeView.prompt", fallback: "SideStore's Developer Mode gives access to a menu with some debugging actions commonly used by developers. **However, some of them can break SideStore if used in the wrong way.**\n\nYou should only enable Developer Mode if you meet one of the following requirements:\n- You are a SideStore developer or contributor\n- You were asked to do this by a helper when getting support\n- You were asked to do this when you reported a bug or helped a developer test a change\n\n**_We will not provide support if you break SideStore with Developer Mode._**")
|
||||
/// Read the text!
|
||||
internal static let read = L10n.tr("Localizable", "DevModeView.read", fallback: "Read the text!")
|
||||
/// Skip Resign
|
||||
internal static let skipResign = L10n.tr("Localizable", "DevModeView.skipResign", fallback: "Skip Resign")
|
||||
/// DevModeView
|
||||
internal static let title = L10n.tr("Localizable", "DevModeView.title", fallback: "Developer Mode")
|
||||
/// Temporary File Explorer
|
||||
internal static let tmpExplorer = L10n.tr("Localizable", "DevModeView.tmpExplorer", fallback: "Temporary File Explorer")
|
||||
internal enum Minimuxer {
|
||||
/// AFC File Explorer (check footer for notes)
|
||||
internal static let afcExplorer = L10n.tr("Localizable", "DevModeView.Minimuxer.afcExplorer", fallback: "AFC File Explorer (check footer for notes)")
|
||||
/// Dump provisioning profiles to Documents directory
|
||||
internal static let dumpProfiles = L10n.tr("Localizable", "DevModeView.Minimuxer.dumpProfiles", fallback: "Dump provisioning profiles to Documents directory")
|
||||
/// Notes on AFC File Explorer:
|
||||
/// - If nothing shows up, check minimuxer logs for error
|
||||
/// - It is currently extremely very unoptimized and may be very slow; a new AFC client is created for every action
|
||||
/// - It is currently limited to a maximum depth of 3 to ensure it doesn't take too long to iterate over everything when you open it
|
||||
/// - Very buggy
|
||||
/// - There are multiple unimplemented actions
|
||||
internal static let footer = L10n.tr("Localizable", "DevModeView.Minimuxer.footer", fallback: "Notes on AFC File Explorer:\n- If nothing shows up, check minimuxer logs for error\n- It is currently extremely very unoptimized and may be very slow; a new AFC client is created for every action\n- It is currently limited to a maximum depth of 3 to ensure it doesn't take too long to iterate over everything when you open it\n- Very buggy\n- There are multiple unimplemented actions")
|
||||
}
|
||||
}
|
||||
internal enum MyAppsView {
|
||||
/// MyAppsView
|
||||
internal static let active = L10n.tr("Localizable", "MyAppsView.active", fallback: "Active")
|
||||
/// App IDs Remaining
|
||||
internal static let appIDsRemaining = L10n.tr("Localizable", "MyAppsView.appIDsRemaining", fallback: "App IDs Remaining")
|
||||
/// apps
|
||||
internal static let apps = L10n.tr("Localizable", "MyAppsView.apps", fallback: "apps")
|
||||
/// Failed to refresh
|
||||
internal static let failedToRefresh = L10n.tr("Localizable", "MyAppsView.failedToRefresh", fallback: "Failed to refresh")
|
||||
/// My Apps
|
||||
internal static let myApps = L10n.tr("Localizable", "MyAppsView.myApps", fallback: "My Apps")
|
||||
/// Refresh All
|
||||
internal static let refreshAll = L10n.tr("Localizable", "MyAppsView.refreshAll", fallback: "Refresh All")
|
||||
/// Sideloading in progress...
|
||||
internal static let sideloading = L10n.tr("Localizable", "MyAppsView.sideloading", fallback: "Sideloading in progress...")
|
||||
/// Keep this lowercase
|
||||
internal static let viewAppIDs = L10n.tr("Localizable", "MyAppsView.viewAppIDs", fallback: "View App IDs")
|
||||
internal enum Hints {
|
||||
internal enum NoUpdates {
|
||||
/// Dismiss for now
|
||||
internal static let dismissForNow = L10n.tr("Localizable", "MyAppsView.Hints.NoUpdates.dismissForNow", fallback: "Dismiss for now")
|
||||
/// Don't show this again
|
||||
internal static let dontShowAgain = L10n.tr("Localizable", "MyAppsView.Hints.NoUpdates.dontShowAgain", fallback: "Don't show this again")
|
||||
/// You will be notified once updates for your apps are available. The updates will then be shown here.
|
||||
internal static let text = L10n.tr("Localizable", "MyAppsView.Hints.NoUpdates.text", fallback: "You will be notified once updates for your apps are available. The updates will then be shown here.")
|
||||
/// All Apps are Up To Date
|
||||
internal static let title = L10n.tr("Localizable", "MyAppsView.Hints.NoUpdates.title", fallback: "All Apps are Up To Date")
|
||||
}
|
||||
}
|
||||
}
|
||||
internal enum NewsView {
|
||||
/// NewsView
|
||||
internal static let title = L10n.tr("Localizable", "NewsView.title", fallback: "News")
|
||||
internal enum Section {
|
||||
internal enum FromSources {
|
||||
/// From your Sources
|
||||
internal static let title = L10n.tr("Localizable", "NewsView.Section.FromSources.title", fallback: "From your Sources")
|
||||
}
|
||||
}
|
||||
}
|
||||
internal enum RootView {
|
||||
/// Browse
|
||||
internal static let browse = L10n.tr("Localizable", "RootView.browse", fallback: "Browse")
|
||||
/// My Apps
|
||||
internal static let myApps = L10n.tr("Localizable", "RootView.myApps", fallback: "My Apps")
|
||||
/// RootView
|
||||
internal static let news = L10n.tr("Localizable", "RootView.news", fallback: "News")
|
||||
/// Settings
|
||||
internal static let settings = L10n.tr("Localizable", "RootView.settings", fallback: "Settings")
|
||||
}
|
||||
internal enum SettingsView {
|
||||
/// Add to Siri...
|
||||
internal static let addToSiri = L10n.tr("Localizable", "SettingsView.addToSiri", fallback: "Add to Siri...")
|
||||
/// Background Refresh
|
||||
internal static let backgroundRefresh = L10n.tr("Localizable", "SettingsView.backgroundRefresh", fallback: "Background Refresh")
|
||||
/// Connect your Apple ID
|
||||
internal static let connectAppleID = L10n.tr("Localizable", "SettingsView.connectAppleID", fallback: "Connect your Apple ID")
|
||||
/// Credits
|
||||
internal static let credits = L10n.tr("Localizable", "SettingsView.credits", fallback: "Credits")
|
||||
/// Debug
|
||||
internal static let debug = L10n.tr("Localizable", "SettingsView.debug", fallback: "Debug")
|
||||
/// Debug Logging
|
||||
internal static let debugLogging = L10n.tr("Localizable", "SettingsView.debugLogging", fallback: "Debug Logging")
|
||||
/// Export Logs
|
||||
internal static let exportLogs = L10n.tr("Localizable", "SettingsView.exportLogs", fallback: "Export Logs")
|
||||
/// Refreshing Apps
|
||||
internal static let refreshingApps = L10n.tr("Localizable", "SettingsView.refreshingApps", fallback: "Refreshing Apps")
|
||||
/// Enable Background Refresh to automatically refresh apps in the background when connected to WiFi and with Wireguard active.
|
||||
internal static let refreshingAppsFooter = L10n.tr("Localizable", "SettingsView.refreshingAppsFooter", fallback: "Enable Background Refresh to automatically refresh apps in the background when connected to WiFi and with Wireguard active.")
|
||||
/// Reset Image Cache
|
||||
internal static let resetImageCache = L10n.tr("Localizable", "SettingsView.resetImageCache", fallback: "Reset Image Cache")
|
||||
/// SwiftUI Redesign
|
||||
internal static let swiftUIRedesign = L10n.tr("Localizable", "SettingsView.swiftUIRedesign", fallback: "SwiftUI Redesign")
|
||||
/// Switch to UIKit
|
||||
internal static let switchToUIKit = L10n.tr("Localizable", "SettingsView.switchToUIKit", fallback: "Switch to UIKit")
|
||||
/// Settings
|
||||
internal static let title = L10n.tr("Localizable", "SettingsView.title", fallback: "Settings")
|
||||
internal enum ConnectedAppleID {
|
||||
/// E-Mail
|
||||
internal static let eMail = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.eMail", fallback: "E-Mail")
|
||||
/// SettingsView
|
||||
internal static let name = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.name", fallback: "Name")
|
||||
/// Sign Out
|
||||
internal static let signOut = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.signOut", fallback: "Sign Out")
|
||||
/// Connected Apple ID
|
||||
internal static let text = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.text", fallback: "Connected Apple ID")
|
||||
/// Type
|
||||
internal static let type = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.type", fallback: "Type")
|
||||
internal enum Footer {
|
||||
/// Your Apple ID is required to sign the apps you install with SideStore.
|
||||
internal static let p1 = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.Footer.p1", fallback: "Your Apple ID is required to sign the apps you install with SideStore.")
|
||||
/// Your credentials are only sent to Apple's servers and are not accessible by the SideStore Team. Once successfully logged in, the login details are stored securely on your device.
|
||||
internal static let p2 = L10n.tr("Localizable", "SettingsView.ConnectedAppleID.Footer.p2", fallback: "Your credentials are only sent to Apple's servers and are not accessible by the SideStore Team. Once successfully logged in, the login details are stored securely on your device.")
|
||||
}
|
||||
}
|
||||
}
|
||||
internal enum SourcesView {
|
||||
/// Done
|
||||
internal static let done = L10n.tr("Localizable", "SourcesView.done", fallback: "Done")
|
||||
/// Remove
|
||||
internal static let remove = L10n.tr("Localizable", "SourcesView.remove", fallback: "Remove")
|
||||
/// SideStore has reviewed these sources to make sure they meet our safety standards.
|
||||
internal static let reviewedText = L10n.tr("Localizable", "SourcesView.reviewedText", fallback: "SideStore has reviewed these sources to make sure they meet our safety standards.")
|
||||
/// Sources
|
||||
internal static let sources = L10n.tr("Localizable", "SourcesView.sources", fallback: "Sources")
|
||||
/// SourcesView
|
||||
internal static let sourcesDescription = L10n.tr("Localizable", "SourcesView.sourcesDescription", fallback: "Sources control what apps are available to download through SideStore.")
|
||||
/// Trusted Sources
|
||||
internal static let trustedSources = L10n.tr("Localizable", "SourcesView.trustedSources", fallback: "Trusted Sources")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
|
||||
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
|
||||
|
||||
// MARK: - Implementation Details
|
||||
|
||||
extension L10n {
|
||||
private static func tr(_ table: String, _ key: String, _ args: CVarArg..., fallback value: String) -> String {
|
||||
let format = BundleToken.bundle.localizedString(forKey: key, value: value, table: table)
|
||||
return String(format: format, locale: Locale.current, arguments: args)
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable convenience_type
|
||||
private final class BundleToken {
|
||||
static let bundle: Bundle = {
|
||||
#if SWIFT_PACKAGE
|
||||
return Bundle.module
|
||||
#else
|
||||
return Bundle(for: BundleToken.self)
|
||||
#endif
|
||||
}()
|
||||
}
|
||||
// swiftlint:enable convenience_type
|
||||
72
AltStore/Helper/DateFormatterHelper.swift
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// DateFormatterHelper.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 20.11.22.
|
||||
// Copyright © 2022 Fabian Thies. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct DateFormatterHelper {
|
||||
|
||||
private static let appExpirationDateFormatter: DateComponentsFormatter = {
|
||||
let dateComponentsFormatter = DateComponentsFormatter()
|
||||
dateComponentsFormatter.zeroFormattingBehavior = [.pad]
|
||||
dateComponentsFormatter.collapsesLargestUnit = false
|
||||
return dateComponentsFormatter
|
||||
}()
|
||||
|
||||
private static let relativeDateFormatter: RelativeDateTimeFormatter = {
|
||||
let formatter = RelativeDateTimeFormatter()
|
||||
formatter.unitsStyle = .abbreviated
|
||||
return formatter
|
||||
}()
|
||||
|
||||
private static let mediumDateFormatter: DateFormatter = {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateStyle = .medium
|
||||
dateFormatter.timeStyle = .none
|
||||
dateFormatter.doesRelativeDateFormatting = true
|
||||
return dateFormatter
|
||||
}()
|
||||
|
||||
private static let timeFormatter: DateFormatter = {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateStyle = .none
|
||||
dateFormatter.timeStyle = .short
|
||||
return dateFormatter
|
||||
}()
|
||||
|
||||
|
||||
|
||||
static func string(forExpirationDate date: Date) -> String {
|
||||
let startDate = Date()
|
||||
let interval = date.timeIntervalSince(startDate)
|
||||
guard interval > 0 else {
|
||||
return "EXPIRED"
|
||||
}
|
||||
|
||||
if interval < (24 * 60 * 60) {
|
||||
self.appExpirationDateFormatter.unitsStyle = .positional
|
||||
self.appExpirationDateFormatter.allowedUnits = [.minute, .second]
|
||||
} else {
|
||||
self.appExpirationDateFormatter.unitsStyle = .full
|
||||
self.appExpirationDateFormatter.allowedUnits = [.day]
|
||||
}
|
||||
|
||||
return self.appExpirationDateFormatter.string(from: startDate, to: date) ?? ""
|
||||
}
|
||||
|
||||
static func string(forRelativeDate date: Date, to referenceDate: Date = Date()) -> String {
|
||||
self.relativeDateFormatter.localizedString(for: date, relativeTo: referenceDate)
|
||||
}
|
||||
|
||||
static func string(for date: Date) -> String {
|
||||
self.mediumDateFormatter.string(from: date)
|
||||
}
|
||||
|
||||
static func timeString(for date: Date) -> String {
|
||||
self.timeFormatter.string(from: date)
|
||||
}
|
||||
}
|
||||
254
AltStore/Helper/SideloadingManager.swift
Normal file
@@ -0,0 +1,254 @@
|
||||
//
|
||||
// SideloadingManager.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 20.12.22.
|
||||
// Copyright © 2022 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import CoreData
|
||||
import AltStoreCore
|
||||
import CAltSign
|
||||
import Roxas
|
||||
|
||||
// TODO: Move this to the AppManager
|
||||
class SideloadingManager {
|
||||
class Context {
|
||||
var fileURL: URL?
|
||||
var application: ALTApplication?
|
||||
var installedApp: InstalledApp? {
|
||||
didSet {
|
||||
self.installedAppContext = self.installedApp?.managedObjectContext
|
||||
}
|
||||
}
|
||||
private var installedAppContext: NSManagedObjectContext?
|
||||
var error: Error?
|
||||
}
|
||||
|
||||
|
||||
public static let shared = SideloadingManager()
|
||||
|
||||
@Published
|
||||
public var progress: Progress?
|
||||
|
||||
private let operationQueue = OperationQueue()
|
||||
|
||||
private init() {}
|
||||
|
||||
|
||||
// TODO: Refactor & convert to async
|
||||
func sideloadApp(at url: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
self.progress = Progress.discreteProgress(totalUnitCount: 100)
|
||||
|
||||
let temporaryDirectory = FileManager.default.uniqueTemporaryURL()
|
||||
let unzippedAppDirectory = temporaryDirectory.appendingPathComponent("App")
|
||||
|
||||
let context = Context()
|
||||
|
||||
let downloadOperation: RSTAsyncBlockOperation?
|
||||
|
||||
if url.isFileURL {
|
||||
downloadOperation = nil
|
||||
context.fileURL = url
|
||||
self.progress?.totalUnitCount -= 20
|
||||
} else {
|
||||
let downloadProgress = Progress.discreteProgress(totalUnitCount: 100)
|
||||
|
||||
downloadOperation = RSTAsyncBlockOperation { (operation) in
|
||||
let downloadTask = URLSession.shared.downloadTask(with: url) { (fileURL, response, error) in
|
||||
do
|
||||
{
|
||||
let (fileURL, _) = try Result((fileURL, response), error).get()
|
||||
|
||||
try FileManager.default.createDirectory(at: temporaryDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
let destinationURL = temporaryDirectory.appendingPathComponent("App.ipa")
|
||||
try FileManager.default.moveItem(at: fileURL, to: destinationURL)
|
||||
|
||||
context.fileURL = destinationURL
|
||||
}
|
||||
catch
|
||||
{
|
||||
context.error = error
|
||||
}
|
||||
operation.finish()
|
||||
}
|
||||
downloadProgress.addChild(downloadTask.progress, withPendingUnitCount: 100)
|
||||
downloadTask.resume()
|
||||
}
|
||||
self.progress?.addChild(downloadProgress, withPendingUnitCount: 20)
|
||||
}
|
||||
|
||||
let unzipProgress = Progress.discreteProgress(totalUnitCount: 1)
|
||||
let unzipAppOperation = BlockOperation {
|
||||
do
|
||||
{
|
||||
if let error = context.error
|
||||
{
|
||||
throw error
|
||||
}
|
||||
|
||||
guard let fileURL = context.fileURL else { throw OperationError.invalidParameters }
|
||||
defer {
|
||||
try? FileManager.default.removeItem(at: fileURL)
|
||||
}
|
||||
|
||||
try FileManager.default.createDirectory(at: unzippedAppDirectory, withIntermediateDirectories: true, attributes: nil)
|
||||
let unzippedApplicationURL = try FileManager.default.unzipAppBundle(at: fileURL, toDirectory: unzippedAppDirectory)
|
||||
|
||||
guard let application = ALTApplication(fileURL: unzippedApplicationURL) else { throw OperationError.invalidApp }
|
||||
context.application = application
|
||||
|
||||
unzipProgress.completedUnitCount = 1
|
||||
}
|
||||
catch
|
||||
{
|
||||
context.error = error
|
||||
}
|
||||
}
|
||||
self.progress?.addChild(unzipProgress, withPendingUnitCount: 10)
|
||||
|
||||
if let downloadOperation = downloadOperation
|
||||
{
|
||||
unzipAppOperation.addDependency(downloadOperation)
|
||||
}
|
||||
|
||||
let removeAppExtensionsProgress = Progress.discreteProgress(totalUnitCount: 1)
|
||||
|
||||
let removeAppExtensionsOperation = RSTAsyncBlockOperation { [weak self] (operation) in
|
||||
do
|
||||
{
|
||||
if let error = context.error
|
||||
{
|
||||
throw error
|
||||
}
|
||||
|
||||
guard let application = context.application else { throw OperationError.invalidParameters }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self?.removeAppExtensions(from: application) { (result) in
|
||||
switch result
|
||||
{
|
||||
case .success: removeAppExtensionsProgress.completedUnitCount = 1
|
||||
case .failure(let error): context.error = error
|
||||
}
|
||||
operation.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
context.error = error
|
||||
operation.finish()
|
||||
}
|
||||
}
|
||||
removeAppExtensionsOperation.addDependency(unzipAppOperation)
|
||||
self.progress?.addChild(removeAppExtensionsProgress, withPendingUnitCount: 5)
|
||||
|
||||
let installProgress = Progress.discreteProgress(totalUnitCount: 100)
|
||||
let installAppOperation = RSTAsyncBlockOperation { (operation) in
|
||||
do
|
||||
{
|
||||
if let error = context.error
|
||||
{
|
||||
throw error
|
||||
}
|
||||
|
||||
guard let application = context.application else { throw OperationError.invalidParameters }
|
||||
|
||||
let group = AppManager.shared.install(application, presentingViewController: nil) { (result) in
|
||||
switch result
|
||||
{
|
||||
case .success(let installedApp): context.installedApp = installedApp
|
||||
case .failure(let error): context.error = error
|
||||
}
|
||||
operation.finish()
|
||||
}
|
||||
installProgress.addChild(group.progress, withPendingUnitCount: 100)
|
||||
}
|
||||
catch
|
||||
{
|
||||
context.error = error
|
||||
operation.finish()
|
||||
}
|
||||
}
|
||||
installAppOperation.completionBlock = {
|
||||
try? FileManager.default.removeItem(at: temporaryDirectory)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.progress = nil
|
||||
|
||||
switch Result(context.installedApp, context.error)
|
||||
{
|
||||
case .success(let app):
|
||||
completion(.success(()))
|
||||
|
||||
app.managedObjectContext?.perform {
|
||||
print("Successfully installed app:", app.bundleIdentifier)
|
||||
}
|
||||
|
||||
case .failure(OperationError.cancelled):
|
||||
completion(.failure((OperationError.cancelled)))
|
||||
|
||||
case .failure(let error):
|
||||
NotificationManager.shared.reportError(error: error)
|
||||
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
self.progress?.addChild(installProgress, withPendingUnitCount: 65)
|
||||
installAppOperation.addDependency(removeAppExtensionsOperation)
|
||||
|
||||
let operations = [downloadOperation, unzipAppOperation, removeAppExtensionsOperation, installAppOperation].compactMap { $0 }
|
||||
self.operationQueue.addOperations(operations, waitUntilFinished: false)
|
||||
}
|
||||
|
||||
|
||||
// TODO: Refactor
|
||||
private func removeAppExtensions(from application: ALTApplication, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
{
|
||||
guard !application.appExtensions.isEmpty else { return completion(.success(())) }
|
||||
|
||||
let firstSentence: String
|
||||
|
||||
if UserDefaults.standard.activeAppLimitIncludesExtensions
|
||||
{
|
||||
firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to 3 active apps and app extensions.", comment: "")
|
||||
}
|
||||
else
|
||||
{
|
||||
firstSentence = NSLocalizedString("Non-developer Apple IDs are limited to creating 10 App IDs per week.", comment: "")
|
||||
}
|
||||
|
||||
let message = firstSentence + " " + NSLocalizedString("Would you like to remove this app's extensions so they don't count towards your limit?", comment: "")
|
||||
|
||||
let alertController = UIAlertController(title: NSLocalizedString("App Contains Extensions", comment: ""), message: message, preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: UIAlertAction.cancel.title, style: UIAlertAction.cancel.style, handler: { (action) in
|
||||
completion(.failure(OperationError.cancelled))
|
||||
}))
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Keep App Extensions", comment: ""), style: .default) { (action) in
|
||||
completion(.success(()))
|
||||
})
|
||||
alertController.addAction(UIAlertAction(title: NSLocalizedString("Remove App Extensions", comment: ""), style: .destructive) { (action) in
|
||||
do
|
||||
{
|
||||
for appExtension in application.appExtensions
|
||||
{
|
||||
try FileManager.default.removeItem(at: appExtension.fileURL)
|
||||
}
|
||||
|
||||
completion(.success(()))
|
||||
}
|
||||
catch
|
||||
{
|
||||
completion(.failure(error))
|
||||
}
|
||||
})
|
||||
|
||||
let rootViewController = UIApplication.shared.keyWindow?.rootViewController
|
||||
rootViewController?.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
@@ -204,6 +204,8 @@
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>UISupportsDocumentBrowser</key>
|
||||
<true/>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import Roxas
|
||||
import EmotionalDamage
|
||||
import minimuxer
|
||||
@@ -42,7 +43,10 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg
|
||||
{
|
||||
defer {
|
||||
// Create destinationViewController now so view controllers can register for receiving Notifications.
|
||||
self.destinationViewController = self.storyboard!.instantiateViewController(withIdentifier: "tabBarController") as! TabBarController
|
||||
// self.destinationViewController = self.storyboard!.instantiateViewController(withIdentifier: "tabBarController") as! TabBarController
|
||||
let rootView = RootView()
|
||||
.environment(\.managedObjectContext, DatabaseManager.shared.viewContext)
|
||||
self.destinationViewController = UIHostingController(rootView: rootView)
|
||||
}
|
||||
super.viewDidLoad()
|
||||
}
|
||||
@@ -50,15 +54,29 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(true)
|
||||
#if !targetEnvironment(simulator)
|
||||
if !UserDefaults.standard.onboardingComplete {
|
||||
self.showOnboarding()
|
||||
return
|
||||
}
|
||||
|
||||
start_em_proxy(bind_addr: Consts.Proxy.serverURL)
|
||||
|
||||
guard let pf = fetchPairingFile() else {
|
||||
displayError("Device pairing file not found.")
|
||||
self.showOnboarding(step: .pairing)
|
||||
return
|
||||
}
|
||||
start_minimuxer_threads(pf)
|
||||
#endif
|
||||
}
|
||||
|
||||
func showOnboarding(step: OnboardingView.OnboardingStep = .welcome) {
|
||||
let onboardingView = OnboardingView(onDismiss: { self.dismiss(animated: true) }, currentStep: step)
|
||||
.environment(\.managedObjectContext, DatabaseManager.shared.viewContext)
|
||||
let navigationController = UINavigationController(rootViewController: UIHostingController(rootView: onboardingView))
|
||||
navigationController.isNavigationBarHidden = true
|
||||
navigationController.isModalInPresentation = true
|
||||
self.present(navigationController, animated: true)
|
||||
}
|
||||
|
||||
func fetchPairingFile() -> String? {
|
||||
let filename = "ALTPairingFile.mobiledevicepairing"
|
||||
@@ -155,6 +173,7 @@ final class LaunchViewController: RSTLaunchViewController, UIDocumentPickerDeleg
|
||||
try! FileManager.default.removeItem(at: FileManager.default.documentsDirectory.appendingPathComponent("\(pairingFileName)"))
|
||||
displayError("minimuxer failed to start, please restart SideStore. \((error as? LocalizedError)?.failureReason ?? "UNKNOWN ERROR!!!!!! REPORT TO GITHUB ISSUES!")")
|
||||
}
|
||||
set_debug(UserDefaults.shared.isDebugLoggingEnabled)
|
||||
start_auto_mounter(documentsDirectory)
|
||||
}
|
||||
}
|
||||
|
||||
80
AltStore/Manager/NotificationManager.swift
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// NotificationManager.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 21.11.22.
|
||||
// Copyright © 2022 Fabian Thies. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AltStoreCore
|
||||
|
||||
class NotificationManager: ObservableObject {
|
||||
|
||||
struct Notification: Identifiable {
|
||||
let id: UUID
|
||||
let title: String
|
||||
let message: String?
|
||||
}
|
||||
|
||||
static let shared = NotificationManager()
|
||||
|
||||
@Published
|
||||
var notifications: [UUID: Notification] = [:]
|
||||
|
||||
private init() {}
|
||||
|
||||
func reportError(error: Error) {
|
||||
if case OperationError.cancelled = error {
|
||||
// Ignore
|
||||
return
|
||||
}
|
||||
|
||||
var error = error as NSError
|
||||
var underlyingError = error.underlyingError
|
||||
|
||||
if
|
||||
let unwrappedUnderlyingError = underlyingError,
|
||||
error.domain == AltServerErrorDomain && error.code == ALTServerError.Code.underlyingError.rawValue
|
||||
{
|
||||
// Treat underlyingError as the primary error.
|
||||
|
||||
error = unwrappedUnderlyingError as NSError
|
||||
underlyingError = nil
|
||||
}
|
||||
|
||||
let text: String
|
||||
let detailText: String?
|
||||
|
||||
if let failure = error.localizedFailure
|
||||
{
|
||||
text = failure
|
||||
detailText = error.localizedFailureReason ?? error.localizedRecoverySuggestion ?? underlyingError?.localizedDescription ?? error.localizedDescription
|
||||
}
|
||||
else if let reason = error.localizedFailureReason
|
||||
{
|
||||
text = reason
|
||||
detailText = error.localizedRecoverySuggestion ?? underlyingError?.localizedDescription
|
||||
}
|
||||
else
|
||||
{
|
||||
text = error.localizedDescription
|
||||
detailText = underlyingError?.localizedDescription ?? error.localizedRecoverySuggestion
|
||||
}
|
||||
|
||||
self.showNotification(title: text, detailText: detailText)
|
||||
}
|
||||
|
||||
func showNotification(title: String, detailText: String? = nil) {
|
||||
let notificationId = UUID()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.notifications[notificationId] = Notification(id: notificationId, title: title, message: detailText)
|
||||
}
|
||||
|
||||
let dismissWorkItem = DispatchWorkItem {
|
||||
self.notifications.removeValue(forKey: notificationId)
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now().advanced(by: .seconds(5)), execute: dismissWorkItem)
|
||||
}
|
||||
}
|
||||
56
AltStore/Manager/OutputCapturer.swift
Normal file
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// OutputCapturer.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 12.02.23.
|
||||
// Copyright © 2023 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import LocalConsole
|
||||
|
||||
class OutputCapturer {
|
||||
|
||||
public static let shared = OutputCapturer()
|
||||
|
||||
private let consoleManager = LCManager.shared
|
||||
|
||||
private var inputPipe = Pipe()
|
||||
private var errorPipe = Pipe()
|
||||
private var outputPipe = Pipe()
|
||||
|
||||
private init() {
|
||||
// Setup pipe file handlers
|
||||
self.inputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in
|
||||
self?.handle(data: fileHandle.availableData)
|
||||
}
|
||||
self.errorPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in
|
||||
self?.handle(data: fileHandle.availableData, isError: true)
|
||||
}
|
||||
|
||||
// Keep STDOUT
|
||||
dup2(STDOUT_FILENO, self.outputPipe.fileHandleForWriting.fileDescriptor)
|
||||
|
||||
// Intercept STDOUT and STDERR
|
||||
dup2(self.inputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)
|
||||
dup2(self.errorPipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO)
|
||||
}
|
||||
|
||||
deinit {
|
||||
try? self.inputPipe.fileHandleForReading.close()
|
||||
try? self.errorPipe.fileHandleForReading.close()
|
||||
}
|
||||
|
||||
private func handle(data: Data, isError: Bool = false) {
|
||||
// Write output to STDOUT
|
||||
self.outputPipe.fileHandleForWriting.write(data)
|
||||
|
||||
guard let string = String(data: data, encoding: .utf8) else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.consoleManager.print(string)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import Roxas
|
||||
import Network
|
||||
|
||||
@@ -39,17 +40,17 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
|
||||
let context: AuthenticatedOperationContext
|
||||
|
||||
private weak var presentingViewController: UIViewController?
|
||||
|
||||
private lazy var navigationController: UINavigationController = {
|
||||
let navigationController = self.storyboard.instantiateViewController(withIdentifier: "navigationController") as! UINavigationController
|
||||
if #available(iOS 13.0, *)
|
||||
{
|
||||
navigationController.isModalInPresentation = true
|
||||
}
|
||||
return navigationController
|
||||
}()
|
||||
|
||||
private lazy var storyboard = UIStoryboard(name: "Authentication", bundle: nil)
|
||||
|
||||
// private lazy var navigationController: UINavigationController = {
|
||||
// let navigationController = self.storyboard.instantiateViewController(withIdentifier: "navigationController") as! UINavigationController
|
||||
// if #available(iOS 13.0, *)
|
||||
// {
|
||||
// navigationController.isModalInPresentation = true
|
||||
// }
|
||||
// return navigationController
|
||||
// }()
|
||||
//
|
||||
// private lazy var storyboard = UIStoryboard(name: "Authentication", bundle: nil)
|
||||
|
||||
private var appleIDEmailAddress: String?
|
||||
private var appleIDPassword: String?
|
||||
@@ -266,7 +267,8 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
|
||||
super.finish(result)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.navigationController.dismiss(animated: true, completion: nil)
|
||||
// self.navigationController.dismiss(animated: true, completion: nil)
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,7 +278,8 @@ final class AuthenticationOperation: ResultOperation<(ALTTeam, ALTCertificate, A
|
||||
super.finish(result)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.navigationController.dismiss(animated: true, completion: nil)
|
||||
// self.navigationController.dismiss(animated: true, completion: nil)
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,25 +290,33 @@ private extension AuthenticationOperation
|
||||
{
|
||||
func present(_ viewController: UIViewController) -> Bool
|
||||
{
|
||||
guard let presentingViewController = self.presentingViewController else { return false }
|
||||
|
||||
self.navigationController.view.tintColor = .white
|
||||
|
||||
if self.navigationController.viewControllers.isEmpty
|
||||
{
|
||||
guard presentingViewController.presentedViewController == nil else { return false }
|
||||
|
||||
self.navigationController.setViewControllers([viewController], animated: false)
|
||||
presentingViewController.present(self.navigationController, animated: true, completion: nil)
|
||||
}
|
||||
else
|
||||
{
|
||||
viewController.navigationItem.leftBarButtonItem = nil
|
||||
self.navigationController.pushViewController(viewController, animated: true)
|
||||
}
|
||||
UIApplication.shared.keyWindow?.rootViewController?.present(viewController, animated: true)
|
||||
// guard let presentingViewController = self.presentingViewController else { return false }
|
||||
//
|
||||
// self.navigationController.view.tintColor = .white
|
||||
//
|
||||
// if self.navigationController.viewControllers.isEmpty
|
||||
// {
|
||||
// guard presentingViewController.presentedViewController == nil else { return false }
|
||||
//
|
||||
// self.navigationController.setViewControllers([viewController], animated: false)
|
||||
// presentingViewController.present(self.navigationController, animated: true, completion: nil)
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// viewController.navigationItem.leftBarButtonItem = nil
|
||||
// self.navigationController.pushViewController(viewController, animated: true)
|
||||
// }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func dismiss() {
|
||||
if let presentingViewController {
|
||||
presentingViewController.dismiss(animated: true)
|
||||
}
|
||||
// UIApplication.shared.keyWindow?.rootViewController?.presentedViewController?.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
private extension AuthenticationOperation
|
||||
@@ -315,29 +326,29 @@ private extension AuthenticationOperation
|
||||
func authenticate()
|
||||
{
|
||||
DispatchQueue.main.async {
|
||||
let authenticationViewController = self.storyboard.instantiateViewController(withIdentifier: "authenticationViewController") as! AuthenticationViewController
|
||||
authenticationViewController.authenticationHandler = { (appleID, password, completionHandler) in
|
||||
self.authenticate(appleID: appleID, password: password) { (result) in
|
||||
completionHandler(result)
|
||||
let viewController = UIHostingController(rootView: NavigationView {
|
||||
ConnectAppleIDView { appleID, password, completionHandler in
|
||||
self.authenticate(appleID: appleID, password: password) { (result) in
|
||||
completionHandler(result)
|
||||
}
|
||||
} completionHandler: { result in
|
||||
if let (account, session, password) = result
|
||||
{
|
||||
// We presented the Auth UI and the user signed in.
|
||||
// In this case, we'll assume we should show the instructions again.
|
||||
self.shouldShowInstructions = true
|
||||
|
||||
self.appleIDPassword = password
|
||||
completionHandler(.success((account, session)))
|
||||
}
|
||||
else
|
||||
{
|
||||
completionHandler(.failure(OperationError.cancelled))
|
||||
}
|
||||
}
|
||||
}
|
||||
authenticationViewController.completionHandler = { (result) in
|
||||
if let (account, session, password) = result
|
||||
{
|
||||
// We presented the Auth UI and the user signed in.
|
||||
// In this case, we'll assume we should show the instructions again.
|
||||
self.shouldShowInstructions = true
|
||||
|
||||
self.appleIDPassword = password
|
||||
completionHandler(.success((account, session)))
|
||||
}
|
||||
else
|
||||
{
|
||||
completionHandler(.failure(OperationError.cancelled))
|
||||
}
|
||||
}
|
||||
}.navigationViewStyle(StackNavigationViewStyle()))
|
||||
|
||||
if !self.present(authenticationViewController)
|
||||
if !self.present(viewController)
|
||||
{
|
||||
completionHandler(.failure(OperationError.notAuthenticated))
|
||||
}
|
||||
@@ -379,8 +390,8 @@ private extension AuthenticationOperation
|
||||
case .success(let anisetteData):
|
||||
let verificationHandler: ((@escaping (String?) -> Void) -> Void)?
|
||||
|
||||
if let presentingViewController = self.presentingViewController
|
||||
{
|
||||
// if let presentingViewController = self.presentingViewController
|
||||
// {
|
||||
verificationHandler = { (completionHandler) in
|
||||
DispatchQueue.main.async {
|
||||
let alertController = UIAlertController(title: NSLocalizedString("Please enter the 6-digit verification code that was sent to your Apple devices.", comment: ""), message: nil, preferredStyle: .alert)
|
||||
@@ -406,22 +417,23 @@ private extension AuthenticationOperation
|
||||
completionHandler(nil)
|
||||
})
|
||||
|
||||
if self.navigationController.presentingViewController != nil
|
||||
{
|
||||
self.navigationController.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
else
|
||||
{
|
||||
presentingViewController.present(alertController, animated: true, completion: nil)
|
||||
let keyWindow = UIApplication.shared.windows.filter { $0.isKeyWindow }.first
|
||||
|
||||
if var topController = keyWindow?.rootViewController {
|
||||
while let presentedViewController = topController.presentedViewController {
|
||||
topController = presentedViewController
|
||||
}
|
||||
|
||||
topController.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No view controller to present security code alert, so don't provide verificationHandler.
|
||||
verificationHandler = nil
|
||||
}
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // No view controller to present security code alert, so don't provide verificationHandler.
|
||||
// verificationHandler = nil
|
||||
// }
|
||||
|
||||
ALTAppleAPI.shared.authenticate(appleID: appleID, password: password, anisetteData: anisetteData,
|
||||
verificationHandler: verificationHandler) { (account, session, error) in
|
||||
@@ -452,15 +464,15 @@ private extension AuthenticationOperation
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
let selectTeamViewController = self.storyboard.instantiateViewController(withIdentifier: "selectTeamViewController") as! SelectTeamViewController
|
||||
|
||||
selectTeamViewController.teams = teams
|
||||
selectTeamViewController.completionHandler = completionHandler
|
||||
|
||||
if !self.present(selectTeamViewController)
|
||||
{
|
||||
return completionHandler(.failure(AuthenticationError.noTeam))
|
||||
}
|
||||
// let selectTeamViewController = self.storyboard.instantiateViewController(withIdentifier: "selectTeamViewController") as! SelectTeamViewController
|
||||
//
|
||||
// selectTeamViewController.teams = teams
|
||||
// selectTeamViewController.completionHandler = completionHandler
|
||||
//
|
||||
// if !self.present(selectTeamViewController)
|
||||
// {
|
||||
// return completionHandler(.failure(AuthenticationError.noTeam))
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,20 +654,21 @@ private extension AuthenticationOperation
|
||||
|
||||
func showInstructionsIfNecessary(completionHandler: @escaping (Bool) -> Void)
|
||||
{
|
||||
guard self.shouldShowInstructions else { return completionHandler(false) }
|
||||
|
||||
DispatchQueue.main.async {
|
||||
let instructionsViewController = self.storyboard.instantiateViewController(withIdentifier: "instructionsViewController") as! InstructionsViewController
|
||||
instructionsViewController.showsBottomButton = true
|
||||
instructionsViewController.completionHandler = {
|
||||
completionHandler(true)
|
||||
}
|
||||
|
||||
if !self.present(instructionsViewController)
|
||||
{
|
||||
completionHandler(false)
|
||||
}
|
||||
}
|
||||
return completionHandler(false)
|
||||
// guard self.shouldShowInstructions else { return completionHandler(false) }
|
||||
//
|
||||
// DispatchQueue.main.async {
|
||||
// let instructionsViewController = self.storyboard.instantiateViewController(withIdentifier: "instructionsViewController") as! InstructionsViewController
|
||||
// instructionsViewController.showsBottomButton = true
|
||||
// instructionsViewController.completionHandler = {
|
||||
// completionHandler(true)
|
||||
// }
|
||||
//
|
||||
// if !self.present(instructionsViewController)
|
||||
// {
|
||||
// completionHandler(false)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
func showRefreshScreenIfNecessary(signer: ALTSigner, session: ALTAppleAPISession, completionHandler: @escaping (Bool) -> Void)
|
||||
|
||||
@@ -10,11 +10,7 @@ import Foundation
|
||||
|
||||
private extension URL
|
||||
{
|
||||
#if STAGING
|
||||
static let trustedSources = URL(string: "https://raw.githubusercontent.com/SideStore/SideStore/develop/trustedapps.json")!
|
||||
#else
|
||||
static let trustedSources = URL(string: "https://raw.githubusercontent.com/SideStore/SideStore/develop/trustedapps.json")!
|
||||
#endif
|
||||
}
|
||||
|
||||
extension FetchTrustedSourcesOperation
|
||||
|
||||
@@ -163,4 +163,5 @@ extension MinimuxerError: LocalizedError {
|
||||
fileprivate func setArgument(name: String) -> String {
|
||||
return String(format: NSLocalizedString("Cannot set %@ on the device.", comment: ""), name)
|
||||
}
|
||||
return error as! OperationError
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
import Foundation
|
||||
import Roxas
|
||||
import SwiftUI
|
||||
import ZIPFoundation
|
||||
|
||||
import AltStoreCore
|
||||
import AltSign
|
||||
@@ -15,6 +17,9 @@ import AltSign
|
||||
@objc(ResignAppOperation)
|
||||
final class ResignAppOperation: ResultOperation<ALTApplication>
|
||||
{
|
||||
static var skipResign: Bool = false
|
||||
static var skipResignBinding: Binding<Bool> { Binding<Bool>(get: { skipResign }, set: { skipResign = $0 }) }
|
||||
|
||||
let context: InstallAppOperationContext
|
||||
|
||||
init(context: InstallAppOperationContext)
|
||||
@@ -50,6 +55,23 @@ final class ResignAppOperation: ResultOperation<ALTApplication>
|
||||
let prepareAppBundleProgress = self.prepareAppBundle(for: app, profiles: profiles) { (result) in
|
||||
guard let appBundleURL = self.process(result) else { return }
|
||||
|
||||
if ResignAppOperation.skipResign {
|
||||
print("⚠️ WARNING: Skipping resign. Unless you correctly resigned the IPA before installing it, things will not work! Also, this might crash SideStore. You have been warned!")
|
||||
let ipaFile = self.context.temporaryDirectory.appendingPathComponent("App.ipa")
|
||||
let archive = Archive(url: ipaFile, accessMode: .create)!
|
||||
for case let fileURL as URL in FileManager.default.enumerator(at: appBundleURL, includingPropertiesForKeys: [])! {
|
||||
let relative = fileURL.description.replacingOccurrences(of: appBundleURL.description, with: "").removingPercentEncoding!
|
||||
try! archive.addEntry(with: "Payload/App.app\(relative)", fileURL: fileURL)
|
||||
}
|
||||
let destinationURL = InstalledApp.refreshedIPAURL(for: app)
|
||||
try! FileManager.default.copyItem(at: ipaFile, to: destinationURL, shouldReplace: true)
|
||||
|
||||
// Use appBundleURL since we need an app bundle, not .ipa.
|
||||
let resignedApplication = ALTApplication(fileURL: appBundleURL)!
|
||||
self.finish(.success(resignedApplication))
|
||||
return
|
||||
}
|
||||
|
||||
print("Resigning App:", self.context.bundleIdentifier)
|
||||
|
||||
// Resign app bundle
|
||||
|
||||
23
AltStore/Protocols/Filterable.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Filterable.swift
|
||||
// SideStore
|
||||
//
|
||||
// Created by Fabian Thies on 01.12.22.
|
||||
// Copyright © 2022 SideStore. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol Filterable {
|
||||
func matches(_ searchText: String) -> Bool
|
||||
}
|
||||
|
||||
extension Collection where Element: Filterable {
|
||||
func matches(_ searchText: String) -> Bool {
|
||||
self.contains(where: { $0.matches(searchText) })
|
||||
}
|
||||
|
||||
func items(matching searchText: String) -> [Element] {
|
||||
self.filter { $0.matches(searchText) }
|
||||
}
|
||||
}
|
||||
22
AltStore/Protocols/NavigationTab.swift
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// NavigationTab.swift
|
||||
// SideStoreUI
|
||||
//
|
||||
// Created by Fabian Thies on 18.11.22.
|
||||
// Copyright © 2022 Fabian Thies. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SFSafeSymbols
|
||||
|
||||
protocol NavigationTab: RawRepresentable, Identifiable, CaseIterable, Hashable where RawValue == Int {
|
||||
static var defaultTab: Self { get }
|
||||
var displaySymbol: SFSymbol { get }
|
||||
var displayName: String { get }
|
||||
}
|
||||
|
||||
extension NavigationTab {
|
||||
var id: Int {
|
||||
self.rawValue
|
||||
}
|
||||
}
|
||||
11
AltStore/Protocols/ViewModel.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// ViewModel.swift
|
||||
// SideStoreUI
|
||||
//
|
||||
// Created by Fabian Thies on 18.11.22.
|
||||
// Copyright © 2022 Fabian Thies. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
protocol ViewModel: ObservableObject {}
|
||||
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 846 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 997 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
@@ -1 +0,0 @@
|
||||
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFA",
|
||||
"green" : "0x05",
|
||||
"red" : "0xA4"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "riley.jpg",
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
BIN
AltStore/Resources/Assets.xcassets/Honeydew-image.imageset/icon-152.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-60.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-58.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-87.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-180.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-20.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-29.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-58.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-167.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-1024.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 373 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 971 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "shane.jpeg",
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
BIN
AltStore/Resources/Assets.xcassets/Midnight-image.imageset/icon-152.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-60.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-58.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-87.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-180.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-20.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-29.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-58.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-167.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-1024.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 313 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 1011 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
12
AltStore/Resources/Assets.xcassets/Neon-image.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
AltStore/Resources/Assets.xcassets/Neon-image.imageset/icon-152.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
116
AltStore/Resources/Assets.xcassets/Neon.appiconset/Contents.json
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-60.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-58.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-87.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-180.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-20.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-29.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-58.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-40.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-80.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-167.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-1024.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-1024.png
Normal file
|
After Width: | Height: | Size: 501 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-120.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-152.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-167.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-180.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-20.png
Normal file
|
After Width: | Height: | Size: 972 B |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-29.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-40.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-58.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-60.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-76.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-80.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
AltStore/Resources/Assets.xcassets/Neon.appiconset/icon-87.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 43 KiB |
12
AltStore/Resources/Assets.xcassets/Sky-image.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon-152.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
AltStore/Resources/Assets.xcassets/Sky-image.imageset/icon-152.png
vendored
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
114
AltStore/Resources/Assets.xcassets/Sky.appiconset/Contents.json
Normal file
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-20.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-40.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-29.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-58.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-40.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-80.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-76.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-152.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-167.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-40.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-60.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-58.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-87.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-80.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-120.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-120.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-180.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "icon-1024.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"author" : "Iconizer",
|
||||
"version" : "2020.11.0"
|
||||
}
|
||||
BIN
AltStore/Resources/Assets.xcassets/Sky.appiconset/icon-1024.png
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
AltStore/Resources/Assets.xcassets/Sky.appiconset/icon-120.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
AltStore/Resources/Assets.xcassets/Sky.appiconset/icon-152.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
AltStore/Resources/Assets.xcassets/Sky.appiconset/icon-167.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |