Compare commits
239 commits
Author | SHA1 | Date | |
---|---|---|---|
59a333cc20 | |||
9bc9961f34 | |||
0af3732ea9 | |||
5960014da9 | |||
2ab52d3d3e | |||
cd60e0ce1a | |||
ff1d5733a0 | |||
9887a81ef0 | |||
f2ba08e1cc | |||
2b8bc2ecd3 | |||
513c686b64 | |||
aaeb9eaa36 | |||
02a8cb12e9 | |||
be54a58ae6 | |||
8e86e6d205 | |||
283e537c44 | |||
551697eb2c | |||
ab99ef9a0a | |||
02d73de113 | |||
375ea665b4 | |||
a88b9a7fd9 | |||
520315d50f | |||
1bbbdc8194 | |||
d36930b7af | |||
c06e3b59e4 | |||
8cca261e43 | |||
f40aeb9cac | |||
1578896b3e | |||
ba3d8b1882 | |||
04af087c4b | |||
a9398c25af | |||
13d721912b | |||
e3d4e693d2 | |||
86c053344b | |||
a996aace80 | |||
18a1d17230 | |||
69cb9a20f9 | |||
bab2b4be9c | |||
bb005386df | |||
c77bb992b4 | |||
7caf00d07d | |||
6ed760a775 | |||
ecd149b3d2 | |||
9aaf0b2350 | |||
2d6cce6b01 | |||
48faddebea | |||
a8039df22d | |||
e21ec0bd1f | |||
9c42a3d7cc | |||
54a16b2c9a | |||
a6f3068728 | |||
f04258ec04 | |||
8468e51c17 | |||
e9a2d3e151 | |||
1f56fa1b9b | |||
ccad00a094 | |||
51fecb01f5 | |||
c29de44d8c | |||
1d79832544 | |||
a37316c56f | |||
189e10f2b4 | |||
24d5ecd119 | |||
ee6f003073 | |||
7328c00006 | |||
a6fd8d1137 | |||
ea31cda3c2 | |||
8ab7b5ac69 | |||
7aebe530dd | |||
a2afd4f58f | |||
88218cd6ec | |||
c4dee39efe | |||
73651cb7f1 | |||
dd1615f0e3 | |||
6bd14e0f8d | |||
1ca4a74ff0 | |||
c3edabb183 | |||
ba4cc899f8 | |||
5a93184c6d | |||
66754ecc7c | |||
e857439a02 | |||
ed620e86ca | |||
936bc96ff7 | |||
37b441a43d | |||
07af494dcb | |||
49a5c6a56a | |||
4e4d903c44 | |||
abcd4cc321 | |||
6a7df1065d | |||
c0b855ea55 | |||
4c3047b0b9 | |||
899b92e390 | |||
e71c55b488 | |||
361b5f1d84 | |||
ad61600328 | |||
5f1f71068c | |||
3782300b27 | |||
7d47834903 | |||
65a83fa636 | |||
8038e8e6af | |||
eb82a67671 | |||
bc5bb8272a | |||
d2ead5b6d1 | |||
d22370959c | |||
2c9b841f30 | |||
2e3cf4aace | |||
7de563a6eb | |||
3aae2e6623 | |||
5c32c24ae5 | |||
bb56047ee2 | |||
924ada6606 | |||
e6f96d1899 | |||
058500f91e | |||
fd3d9fc2bc | |||
9a7e6b7cb0 | |||
bc2a09891a | |||
7c343eb4e9 | |||
15d7d1dabd | |||
f4ec69a37f | |||
732a253c7a | |||
9c67af8451 | |||
b56da94a7c | |||
e612fbdf7c | |||
f46a0cee17 | |||
4a90d979e3 | |||
9e4323f317 | |||
24ce872849 | |||
1f858414d8 | |||
2d988d48c1 | |||
21d9fd7b59 | |||
cca6472a32 | |||
c769e80bb6 | |||
2986d2b177 | |||
29312d1be2 | |||
9ddf0e65fc | |||
bc74a50a6a | |||
d55d6a0371 | |||
773fdc318b | |||
7423aba92a | |||
77aa50ef19 | |||
dfc213a19a | |||
20900f573f | |||
046a41e8ef | |||
fcd56ab7a0 | |||
923927cddd | |||
219703ecc7 | |||
0739264005 | |||
6f8bec4737 | |||
d8e6e6cfb1 | |||
e7bc857231 | |||
35d249f7c9 | |||
7b7e65bf31 | |||
9542002534 | |||
3020d831e4 | |||
a0e022b8de | |||
b9b3d0e727 | |||
4bf476daea | |||
d1fd97794a | |||
f14ca6e529 | |||
75bb4f43dd | |||
cfd6eed159 | |||
d10adf1fd9 | |||
3b07d56b1d | |||
b4dbda8722 | |||
827765f251 | |||
e7702e1ad0 | |||
70f58aa08d | |||
cf81054366 | |||
f67163e4b0 | |||
9bd967cddf | |||
551e6b1412 | |||
1c76d50bde | |||
2a6afb4092 | |||
b348f37f1a | |||
de757c58f8 | |||
7268b5a38e | |||
b8cf446406 | |||
6e497fae5b | |||
586e4f525e | |||
7f689bbb9c | |||
9dfd9c27c7 | |||
9cf16b2f30 | |||
1299202bba | |||
f16f0d514b | |||
096996c242 | |||
c7bd5a1d94 | |||
20f4eb9c71 | |||
74590542bc | |||
49b1b0e96c | |||
3eec5c0eec | |||
016e4d5d57 | |||
ba071eb4c8 | |||
d2014d3aec | |||
621f0d0864 | |||
eeff60bf98 | |||
245d35db82 | |||
62eeba5334 | |||
46b8fbde29 | |||
9a8568d3fa | |||
a6ccdc029b | |||
ed9a4a598d | |||
13af2d7e3f | |||
2b446833da | |||
0b96b76641 | |||
78eee1e855 | |||
b7937e3580 | |||
9320b2f114 | |||
ad7bc999d3 | |||
b41fd2d6ce | |||
a79a181d6f | |||
fb944f9c48 | |||
3c82af0273 | |||
3577254f08 | |||
abff6218a4 | |||
1be9a7b941 | |||
18381e22e2 | |||
e2273c436a | |||
2296dd4658 | |||
92662665b9 | |||
17387626b8 | |||
e00fd49d89 | |||
97798b2c35 | |||
90a2a19bb1 | |||
21d54cc546 | |||
76638911ee | |||
0b7fed2e9a | |||
328ee2d090 | |||
ebdd5b9feb | |||
f79117eff1 | |||
709dd79e25 | |||
bf7cdc3712 | |||
f12d0600f7 | |||
b6f11e4e08 | |||
76a8f45478 | |||
e03747aa45 | |||
8568d6cc59 | |||
1a0b52d268 | |||
0dea624060 | |||
a4927fd30c | |||
b8be6b79af |
35
.github/workflows/validate_translations.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
name: Validate Translations
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [synchronize, opened, reopened, labeled, unlabeled, edited]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
name: Validate Translations
|
||||||
|
runs-on: macOS-latest
|
||||||
|
steps:
|
||||||
|
- name: git checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: ruby versions
|
||||||
|
run: |
|
||||||
|
ruby --version
|
||||||
|
gem --version
|
||||||
|
bundler --version
|
||||||
|
|
||||||
|
- name: ruby setup
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: 3.3
|
||||||
|
bundler-cache: true
|
||||||
|
|
||||||
|
# additional steps here, if needed
|
||||||
|
|
||||||
|
- name: Clone SwiftPolyglot
|
||||||
|
run: git clone https://github.com/appdecostudio/SwiftPolyglot.git --branch 0.2.0
|
||||||
|
|
||||||
|
- name: Build and Run SwiftPolyglot
|
||||||
|
run: |
|
||||||
|
swift build --package-path ./SwiftPolyglot --configuration release
|
||||||
|
swift run --package-path ./SwiftPolyglot swiftpolyglot "en,eu,be,ca,zh-Hans,zh-Hant,nl,en-GB,fr,de,it,ja,ko,nb,pl,pt-BR,es,tr,uk"
|
|
@ -26,8 +26,6 @@
|
||||||
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F24EEB729360C330042359D /* Preview Assets.xcassets */; };
|
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F24EEB729360C330042359D /* Preview Assets.xcassets */; };
|
||||||
9F295540292B6C3400E0E81B /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F29553F292B6C3400E0E81B /* Timeline */; };
|
9F295540292B6C3400E0E81B /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F29553F292B6C3400E0E81B /* Timeline */; };
|
||||||
9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A540629699698009B2D7C /* SupportAppView.swift */; };
|
9F2A540729699698009B2D7C /* SupportAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A540629699698009B2D7C /* SupportAppView.swift */; };
|
||||||
9F2A540A29699705009B2D7C /* ReceiptParser in Frameworks */ = {isa = PBXBuildFile; productRef = 9F2A540929699705009B2D7C /* ReceiptParser */; };
|
|
||||||
9F2A540C29699705009B2D7C /* RevenueCat in Frameworks */ = {isa = PBXBuildFile; productRef = 9F2A540B29699705009B2D7C /* RevenueCat */; };
|
|
||||||
9F2A540E2969A0B0009B2D7C /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F2A540D2969A0B0009B2D7C /* StoreKit.framework */; };
|
9F2A540E2969A0B0009B2D7C /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F2A540D2969A0B0009B2D7C /* StoreKit.framework */; };
|
||||||
9F2A5411296A1429009B2D7C /* PushNotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A5410296A1429009B2D7C /* PushNotificationsView.swift */; };
|
9F2A5411296A1429009B2D7C /* PushNotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A5410296A1429009B2D7C /* PushNotificationsView.swift */; };
|
||||||
9F2A5419296AB631009B2D7C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A5418296AB631009B2D7C /* NotificationService.swift */; };
|
9F2A5419296AB631009B2D7C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F2A5418296AB631009B2D7C /* NotificationService.swift */; };
|
||||||
|
@ -44,6 +42,11 @@
|
||||||
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4629506F6600B3281A /* NotificationTab.swift */; };
|
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4629506F6600B3281A /* NotificationTab.swift */; };
|
||||||
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB4929506FA100B3281A /* Notifications */; };
|
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9F35DB4929506FA100B3281A /* Notifications */; };
|
||||||
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4B2952005C00B3281A /* MessagesTab.swift */; };
|
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F35DB4B2952005C00B3281A /* MessagesTab.swift */; };
|
||||||
|
9F37BDDB2BE36E22007F28AD /* PostIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDDA2BE36E22007F28AD /* PostIntent.swift */; };
|
||||||
|
9F37BDDD2BE37193007F28AD /* AppIntentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDDC2BE37193007F28AD /* AppIntentService.swift */; };
|
||||||
|
9F37BDDF2BE37C35007F28AD /* TabIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDDE2BE37C35007F28AD /* TabIntent.swift */; };
|
||||||
|
9F37BDE12BE38646007F28AD /* PostImageIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDE02BE38646007F28AD /* PostImageIntent.swift */; };
|
||||||
|
9F37BDE32BE393A7007F28AD /* AppShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F37BDE22BE393A7007F28AD /* AppShortcuts.swift */; };
|
||||||
9F38A7332ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
9F38A7332ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
||||||
9F38A7342ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
9F38A7342ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
||||||
9F38A7352ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
9F38A7352ACEA26100DBCD66 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */; };
|
||||||
|
@ -54,6 +57,9 @@
|
||||||
9F4A48192976B21900A1A038 /* ProfileTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4A48182976B21900A1A038 /* ProfileTab.swift */; };
|
9F4A48192976B21900A1A038 /* ProfileTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F4A48182976B21900A1A038 /* ProfileTab.swift */; };
|
||||||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55C68C2955968700F94077 /* ExploreTab.swift */; };
|
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F55C68C2955968700F94077 /* ExploreTab.swift */; };
|
||||||
9F55C6902955993C00F94077 /* Explore in Frameworks */ = {isa = PBXBuildFile; productRef = 9F55C68F2955993C00F94077 /* Explore */; };
|
9F55C6902955993C00F94077 /* Explore in Frameworks */ = {isa = PBXBuildFile; productRef = 9F55C68F2955993C00F94077 /* Explore */; };
|
||||||
|
9F5BE6272BF492CF0074387E /* ListEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5BE6252BF48FE10074387E /* ListEntity.swift */; };
|
||||||
|
9F5BE6282BF492D10074387E /* ListsWidgetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5BE6232BF48FC40074387E /* ListsWidgetConfiguration.swift */; };
|
||||||
|
9F5BE6292BF492D40074387E /* ListsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5BE6212BF48FBA0074387E /* ListsWidget.swift */; };
|
||||||
9F5E581929545BE700A53960 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5E581829545BE700A53960 /* Env */; };
|
9F5E581929545BE700A53960 /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F5E581829545BE700A53960 /* Env */; };
|
||||||
9F6028562B3F36AE00476078 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6028552B3F36AE00476078 /* AppView.swift */; };
|
9F6028562B3F36AE00476078 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6028552B3F36AE00476078 /* AppView.swift */; };
|
||||||
9F6028582B3F3B7600476078 /* ToolbarTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6028572B3F3B7600476078 /* ToolbarTab.swift */; };
|
9F6028582B3F3B7600476078 /* ToolbarTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F6028572B3F3B7600476078 /* ToolbarTab.swift */; };
|
||||||
|
@ -63,10 +69,30 @@
|
||||||
9F7335EF29674F7100AFF0BA /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F7335EE29674F7100AFF0BA /* QuickLook.framework */; };
|
9F7335EF29674F7100AFF0BA /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F7335EE29674F7100AFF0BA /* QuickLook.framework */; };
|
||||||
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7335F12967608F00AFF0BA /* AddRemoteTimelineView.swift */; };
|
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7335F12967608F00AFF0BA /* AddRemoteTimelineView.swift */; };
|
||||||
9F7335F92968576500AFF0BA /* DisplaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */; };
|
9F7335F92968576500AFF0BA /* DisplaySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */; };
|
||||||
|
9F7788C02BE63935004E6BEF /* InlinePostIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788BF2BE63935004E6BEF /* InlinePostIntent.swift */; };
|
||||||
|
9F7788C72BE652B1004E6BEF /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F7788C62BE652B1004E6BEF /* WidgetKit.framework */; };
|
||||||
|
9F7788C92BE652B1004E6BEF /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F7788C82BE652B1004E6BEF /* SwiftUI.framework */; };
|
||||||
|
9F7788CC2BE652B1004E6BEF /* IceCubesAppWidgetsExtensionBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788CB2BE652B1004E6BEF /* IceCubesAppWidgetsExtensionBundle.swift */; };
|
||||||
|
9F7788CE2BE652B1004E6BEF /* LatestPostsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788CD2BE652B1004E6BEF /* LatestPostsWidget.swift */; };
|
||||||
|
9F7788D02BE652B1004E6BEF /* LatestPostsWidgetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788CF2BE652B1004E6BEF /* LatestPostsWidgetConfiguration.swift */; };
|
||||||
|
9F7788D22BE652B2004E6BEF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F7788D12BE652B2004E6BEF /* Assets.xcassets */; };
|
||||||
|
9F7788D62BE652B2004E6BEF /* IceCubesAppWidgetsExtensionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 9F7788C52BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension.appex */; platformFilters = (ios, maccatalyst, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
9F7788DE2BE6543D004E6BEF /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788DD2BE6543D004E6BEF /* Account */; };
|
||||||
|
9F7788E02BE6543D004E6BEF /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788DF2BE6543D004E6BEF /* AppAccount */; };
|
||||||
|
9F7788E22BE6543D004E6BEF /* Env in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788E12BE6543D004E6BEF /* Env */; };
|
||||||
|
9F7788E42BE6543D004E6BEF /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788E32BE6543D004E6BEF /* Models */; };
|
||||||
|
9F7788E62BE6543D004E6BEF /* Network in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788E52BE6543D004E6BEF /* Network */; };
|
||||||
|
9F7788E82BE65533004E6BEF /* AppAccountEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788E72BE65533004E6BEF /* AppAccountEntity.swift */; };
|
||||||
|
9F7788EA2BE65585004E6BEF /* AppAccountEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788E72BE65533004E6BEF /* AppAccountEntity.swift */; };
|
||||||
|
9F7788ED2BE78D75004E6BEF /* TimelineFilterEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788EC2BE78D75004E6BEF /* TimelineFilterEntity.swift */; };
|
||||||
|
9F7788EE2BE78D7B004E6BEF /* TimelineFilterEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7788EC2BE78D75004E6BEF /* TimelineFilterEntity.swift */; };
|
||||||
|
9F7788F02BE78E77004E6BEF /* Timeline in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7788EF2BE78E77004E6BEF /* Timeline */; };
|
||||||
9F7D93942980063100EE6B7A /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7D93932980063100EE6B7A /* AppAccount */; };
|
9F7D93942980063100EE6B7A /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9F7D93932980063100EE6B7A /* AppAccount */; };
|
||||||
9F7D939A29805DBD00EE6B7A /* AccountSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */; };
|
9F7D939A29805DBD00EE6B7A /* AccountSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */; };
|
||||||
|
9F8B92122BF77DBE003D37A2 /* AccountWidgetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8B920E2BF77DB4003D37A2 /* AccountWidgetConfiguration.swift */; };
|
||||||
|
9F8B92132BF77DBE003D37A2 /* AccountWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8B92102BF77DBB003D37A2 /* AccountWidget.swift */; };
|
||||||
|
9F8B92162BF77F0B003D37A2 /* AccountWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F8B92142BF77F05003D37A2 /* AccountWidgetView.swift */; };
|
||||||
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */; };
|
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */; };
|
||||||
9FAD85832971BF7200496AB1 /* Secret.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9FAD85822971BF7200496AB1 /* Secret.plist */; };
|
|
||||||
9FAD858B29743F7400496AB1 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD858A29743F7400496AB1 /* ShareViewController.swift */; };
|
9FAD858B29743F7400496AB1 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FAD858A29743F7400496AB1 /* ShareViewController.swift */; };
|
||||||
9FAD858E29743F7400496AB1 /* (null) in Resources */ = {isa = PBXBuildFile; };
|
9FAD858E29743F7400496AB1 /* (null) in Resources */ = {isa = PBXBuildFile; };
|
||||||
9FAD859229743F7400496AB1 /* IceCubesShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */; platformFilters = (ios, maccatalyst, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
9FAD859229743F7400496AB1 /* IceCubesShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */; platformFilters = (ios, maccatalyst, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
@ -98,6 +124,13 @@
|
||||||
9FE3DB57296FEFCA00628CB0 /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE3DB56296FEFCA00628CB0 /* AppAccount */; };
|
9FE3DB57296FEFCA00628CB0 /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE3DB56296FEFCA00628CB0 /* AppAccount */; };
|
||||||
9FE4CCAB2B4C848A00DA5F13 /* GiphyUISDK in Frameworks */ = {isa = PBXBuildFile; platformFilters = (ios, maccatalyst, ); productRef = 9FE4CCAA2B4C848A00DA5F13 /* GiphyUISDK */; };
|
9FE4CCAB2B4C848A00DA5F13 /* GiphyUISDK in Frameworks */ = {isa = PBXBuildFile; platformFilters = (ios, maccatalyst, ); productRef = 9FE4CCAA2B4C848A00DA5F13 /* GiphyUISDK */; };
|
||||||
9FE4CCAD2B4C849F00DA5F13 /* GiphyUISDK in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE4CCAC2B4C849F00DA5F13 /* GiphyUISDK */; };
|
9FE4CCAD2B4C849F00DA5F13 /* GiphyUISDK in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE4CCAC2B4C849F00DA5F13 /* GiphyUISDK */; };
|
||||||
|
9FE6A42E2BD043A90055D388 /* RevenueCat in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE6A42D2BD043A90055D388 /* RevenueCat */; };
|
||||||
|
9FF2FB622BE7F5D5001560CE /* HashtagPostsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF2FB602BE7F5A7001560CE /* HashtagPostsWidget.swift */; };
|
||||||
|
9FF2FB632BE7F5D9001560CE /* HashtagPostsWidgetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF2FB5E2BE7F56F001560CE /* HashtagPostsWidgetConfiguration.swift */; };
|
||||||
|
9FF2FB672BE7F816001560CE /* PostsWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF2FB652BE7F805001560CE /* PostsWidgetView.swift */; };
|
||||||
|
9FF2FB6A2BE7F84E001560CE /* SharedUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF2FB682BE7F842001560CE /* SharedUtils.swift */; };
|
||||||
|
9FF2FB702BE8AE9D001560CE /* MentionWidgetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF2FB6E2BE8AE9B001560CE /* MentionWidgetConfiguration.swift */; };
|
||||||
|
9FF2FB712BE8AEA0001560CE /* MentionWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF2FB6C2BE8AE90001560CE /* MentionWidget.swift */; };
|
||||||
9FFF677C299B7B2C00FE700A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677B299B7B2C00FE700A /* Notifications */; };
|
9FFF677C299B7B2C00FE700A /* Notifications in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677B299B7B2C00FE700A /* Notifications */; };
|
||||||
9FFF6780299B7D2B00FE700A /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677F299B7D2B00FE700A /* DesignSystem */; };
|
9FFF6780299B7D2B00FE700A /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF677F299B7D2B00FE700A /* DesignSystem */; };
|
||||||
9FFF6782299B7D3A00FE700A /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF6781299B7D3A00FE700A /* Account */; };
|
9FFF6782299B7D3A00FE700A /* Account in Frameworks */ = {isa = PBXBuildFile; productRef = 9FFF6781299B7D3A00FE700A /* Account */; };
|
||||||
|
@ -123,6 +156,13 @@
|
||||||
remoteGlobalIDString = 9F2A5415296AB631009B2D7C;
|
remoteGlobalIDString = 9F2A5415296AB631009B2D7C;
|
||||||
remoteInfo = IceCubesNotifications;
|
remoteInfo = IceCubesNotifications;
|
||||||
};
|
};
|
||||||
|
9F7788D42BE652B2004E6BEF /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 9FBFE631292A715500C250E9 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 9F7788C42BE652B1004E6BEF;
|
||||||
|
remoteInfo = IceCubesAppWidgetsExtensionExtension;
|
||||||
|
};
|
||||||
9FAD859029743F7400496AB1 /* PBXContainerItemProxy */ = {
|
9FAD859029743F7400496AB1 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 9FBFE631292A715500C250E9 /* Project object */;
|
containerPortal = 9FBFE631292A715500C250E9 /* Project object */;
|
||||||
|
@ -149,6 +189,7 @@
|
||||||
E9DF420729830FEC0003AAD2 /* IceCubesActionExtension.appex in Embed Foundation Extensions */,
|
E9DF420729830FEC0003AAD2 /* IceCubesActionExtension.appex in Embed Foundation Extensions */,
|
||||||
9F2A541D296AB631009B2D7C /* IceCubesNotifications.appex in Embed Foundation Extensions */,
|
9F2A541D296AB631009B2D7C /* IceCubesNotifications.appex in Embed Foundation Extensions */,
|
||||||
9FAD859229743F7400496AB1 /* IceCubesShareExtension.appex in Embed Foundation Extensions */,
|
9FAD859229743F7400496AB1 /* IceCubesShareExtension.appex in Embed Foundation Extensions */,
|
||||||
|
9F7788D62BE652B2004E6BEF /* IceCubesAppWidgetsExtensionExtension.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -197,6 +238,11 @@
|
||||||
9F35DB4629506F6600B3281A /* NotificationTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTab.swift; sourceTree = "<group>"; };
|
9F35DB4629506F6600B3281A /* NotificationTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTab.swift; sourceTree = "<group>"; };
|
||||||
9F35DB4829506F7F00B3281A /* Notifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Notifications; path = Packages/Notifications; sourceTree = "<group>"; };
|
9F35DB4829506F7F00B3281A /* Notifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Notifications; path = Packages/Notifications; sourceTree = "<group>"; };
|
||||||
9F35DB4B2952005C00B3281A /* MessagesTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesTab.swift; sourceTree = "<group>"; };
|
9F35DB4B2952005C00B3281A /* MessagesTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesTab.swift; sourceTree = "<group>"; };
|
||||||
|
9F37BDDA2BE36E22007F28AD /* PostIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostIntent.swift; sourceTree = "<group>"; };
|
||||||
|
9F37BDDC2BE37193007F28AD /* AppIntentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntentService.swift; sourceTree = "<group>"; };
|
||||||
|
9F37BDDE2BE37C35007F28AD /* TabIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabIntent.swift; sourceTree = "<group>"; };
|
||||||
|
9F37BDE02BE38646007F28AD /* PostImageIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostImageIntent.swift; sourceTree = "<group>"; };
|
||||||
|
9F37BDE22BE393A7007F28AD /* AppShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppShortcuts.swift; sourceTree = "<group>"; };
|
||||||
9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
9F38A7322ACEA26100DBCD66 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||||
9F398AA32935F90100A889F2 /* Models */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Models; path = Packages/Models; sourceTree = "<group>"; };
|
9F398AA32935F90100A889F2 /* Models */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Models; path = Packages/Models; sourceTree = "<group>"; };
|
||||||
9F398AA52935FE8A00A889F2 /* AppRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRegistry.swift; sourceTree = "<group>"; };
|
9F398AA52935FE8A00A889F2 /* AppRegistry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRegistry.swift; sourceTree = "<group>"; };
|
||||||
|
@ -205,6 +251,9 @@
|
||||||
9F4A48182976B21900A1A038 /* ProfileTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTab.swift; sourceTree = "<group>"; };
|
9F4A48182976B21900A1A038 /* ProfileTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTab.swift; sourceTree = "<group>"; };
|
||||||
9F55C68C2955968700F94077 /* ExploreTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreTab.swift; sourceTree = "<group>"; };
|
9F55C68C2955968700F94077 /* ExploreTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreTab.swift; sourceTree = "<group>"; };
|
||||||
9F55C68E295598F900F94077 /* Explore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Explore; path = Packages/Explore; sourceTree = "<group>"; };
|
9F55C68E295598F900F94077 /* Explore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Explore; path = Packages/Explore; sourceTree = "<group>"; };
|
||||||
|
9F5BE6212BF48FBA0074387E /* ListsWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsWidget.swift; sourceTree = "<group>"; };
|
||||||
|
9F5BE6232BF48FC40074387E /* ListsWidgetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListsWidgetConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
9F5BE6252BF48FE10074387E /* ListEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListEntity.swift; sourceTree = "<group>"; };
|
||||||
9F5E581729545B5500A53960 /* Env */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Env; path = Packages/Env; sourceTree = "<group>"; };
|
9F5E581729545B5500A53960 /* Env */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Env; path = Packages/Env; sourceTree = "<group>"; };
|
||||||
9F6028552B3F36AE00476078 /* AppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
|
9F6028552B3F36AE00476078 /* AppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
|
||||||
9F6028572B3F3B7600476078 /* ToolbarTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarTab.swift; sourceTree = "<group>"; };
|
9F6028572B3F3B7600476078 /* ToolbarTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarTab.swift; sourceTree = "<group>"; };
|
||||||
|
@ -215,10 +264,24 @@
|
||||||
9F7335EE29674F7100AFF0BA /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.2.sdk/System/Library/Frameworks/QuickLook.framework; sourceTree = DEVELOPER_DIR; };
|
9F7335EE29674F7100AFF0BA /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.2.sdk/System/Library/Frameworks/QuickLook.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
9F7335F12967608F00AFF0BA /* AddRemoteTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddRemoteTimelineView.swift; sourceTree = "<group>"; };
|
9F7335F12967608F00AFF0BA /* AddRemoteTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddRemoteTimelineView.swift; sourceTree = "<group>"; };
|
||||||
9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaySettingsView.swift; sourceTree = "<group>"; };
|
9F7335F82968576500AFF0BA /* DisplaySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplaySettingsView.swift; sourceTree = "<group>"; };
|
||||||
|
9F7788BF2BE63935004E6BEF /* InlinePostIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlinePostIntent.swift; sourceTree = "<group>"; };
|
||||||
|
9F7788C52BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = IceCubesAppWidgetsExtensionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
9F7788C62BE652B1004E6BEF /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||||
|
9F7788C82BE652B1004E6BEF /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||||
|
9F7788CB2BE652B1004E6BEF /* IceCubesAppWidgetsExtensionBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IceCubesAppWidgetsExtensionBundle.swift; sourceTree = "<group>"; };
|
||||||
|
9F7788CD2BE652B1004E6BEF /* LatestPostsWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestPostsWidget.swift; sourceTree = "<group>"; };
|
||||||
|
9F7788CF2BE652B1004E6BEF /* LatestPostsWidgetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestPostsWidgetConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
9F7788D12BE652B2004E6BEF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
9F7788D32BE652B2004E6BEF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
9F7788D72BE652B2004E6BEF /* IceCubesAppWidgetsExtensionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = IceCubesAppWidgetsExtensionExtension.entitlements; sourceTree = "<group>"; };
|
||||||
|
9F7788E72BE65533004E6BEF /* AppAccountEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAccountEntity.swift; sourceTree = "<group>"; };
|
||||||
|
9F7788EC2BE78D75004E6BEF /* TimelineFilterEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineFilterEntity.swift; sourceTree = "<group>"; };
|
||||||
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "IceCubesApp-release.xcconfig"; sourceTree = "<group>"; };
|
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "IceCubesApp-release.xcconfig"; sourceTree = "<group>"; };
|
||||||
9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingView.swift; sourceTree = "<group>"; };
|
9F7D939929805DBD00EE6B7A /* AccountSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingView.swift; sourceTree = "<group>"; };
|
||||||
|
9F8B920E2BF77DB4003D37A2 /* AccountWidgetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountWidgetConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
9F8B92102BF77DBB003D37A2 /* AccountWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountWidget.swift; sourceTree = "<group>"; };
|
||||||
|
9F8B92142BF77F05003D37A2 /* AccountWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountWidgetView.swift; sourceTree = "<group>"; };
|
||||||
9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationSettingsView.swift; sourceTree = "<group>"; };
|
9FA6FD6129C04A8800E2312C /* TranslationSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TranslationSettingsView.swift; sourceTree = "<group>"; };
|
||||||
9FAD85822971BF7200496AB1 /* Secret.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Secret.plist; sourceTree = "<group>"; };
|
|
||||||
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = IceCubesShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = IceCubesShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
9FAD858A29743F7400496AB1 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
9FAD858A29743F7400496AB1 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||||
9FAD858F29743F7400496AB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
9FAD858F29743F7400496AB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
@ -243,6 +306,12 @@
|
||||||
9FE0346A2ADD59AC00529EA8 /* MediaUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = MediaUI; path = Packages/MediaUI; sourceTree = "<group>"; };
|
9FE0346A2ADD59AC00529EA8 /* MediaUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = MediaUI; path = Packages/MediaUI; sourceTree = "<group>"; };
|
||||||
9FE151A5293C90F900E9683D /* IconSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSelectorView.swift; sourceTree = "<group>"; };
|
9FE151A5293C90F900E9683D /* IconSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSelectorView.swift; sourceTree = "<group>"; };
|
||||||
9FE3DB55296FEF5800628CB0 /* AppAccount */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = AppAccount; path = Packages/AppAccount; sourceTree = "<group>"; };
|
9FE3DB55296FEF5800628CB0 /* AppAccount */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = AppAccount; path = Packages/AppAccount; sourceTree = "<group>"; };
|
||||||
|
9FF2FB5E2BE7F56F001560CE /* HashtagPostsWidgetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagPostsWidgetConfiguration.swift; sourceTree = "<group>"; };
|
||||||
|
9FF2FB602BE7F5A7001560CE /* HashtagPostsWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagPostsWidget.swift; sourceTree = "<group>"; };
|
||||||
|
9FF2FB652BE7F805001560CE /* PostsWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsWidgetView.swift; sourceTree = "<group>"; };
|
||||||
|
9FF2FB682BE7F842001560CE /* SharedUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedUtils.swift; sourceTree = "<group>"; };
|
||||||
|
9FF2FB6C2BE8AE90001560CE /* MentionWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionWidget.swift; sourceTree = "<group>"; };
|
||||||
|
9FF2FB6E2BE8AE9B001560CE /* MentionWidgetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionWidgetConfiguration.swift; sourceTree = "<group>"; };
|
||||||
B0BAB49E29B3D7A9008F54D7 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
B0BAB49E29B3D7A9008F54D7 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
C4CBB90B298A0DA3007E1707 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
C4CBB90B298A0DA3007E1707 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
C4FBCF6F298FD88A0015DF22 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
C4FBCF6F298FD88A0015DF22 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
|
@ -278,6 +347,21 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
9F7788C22BE652B1004E6BEF /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
9F7788E42BE6543D004E6BEF /* Models in Frameworks */,
|
||||||
|
9F7788E62BE6543D004E6BEF /* Network in Frameworks */,
|
||||||
|
9F7788E02BE6543D004E6BEF /* AppAccount in Frameworks */,
|
||||||
|
9F7788DE2BE6543D004E6BEF /* Account in Frameworks */,
|
||||||
|
9F7788E22BE6543D004E6BEF /* Env in Frameworks */,
|
||||||
|
9F7788C92BE652B1004E6BEF /* SwiftUI.framework in Frameworks */,
|
||||||
|
9F7788C72BE652B1004E6BEF /* WidgetKit.framework in Frameworks */,
|
||||||
|
9F7788F02BE78E77004E6BEF /* Timeline in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
9FAD858529743F7400496AB1 /* Frameworks */ = {
|
9FAD858529743F7400496AB1 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -300,7 +384,6 @@
|
||||||
9F7335EF29674F7100AFF0BA /* QuickLook.framework in Frameworks */,
|
9F7335EF29674F7100AFF0BA /* QuickLook.framework in Frameworks */,
|
||||||
9FE4CCAB2B4C848A00DA5F13 /* GiphyUISDK in Frameworks */,
|
9FE4CCAB2B4C848A00DA5F13 /* GiphyUISDK in Frameworks */,
|
||||||
9F7335ED2967463400AFF0BA /* AVKit.framework in Frameworks */,
|
9F7335ED2967463400AFF0BA /* AVKit.framework in Frameworks */,
|
||||||
9F2A540C29699705009B2D7C /* RevenueCat in Frameworks */,
|
|
||||||
9F2A540E2969A0B0009B2D7C /* StoreKit.framework in Frameworks */,
|
9F2A540E2969A0B0009B2D7C /* StoreKit.framework in Frameworks */,
|
||||||
9F55C6902955993C00F94077 /* Explore in Frameworks */,
|
9F55C6902955993C00F94077 /* Explore in Frameworks */,
|
||||||
9FAE4ACE29379A5A00772766 /* KeychainSwift in Frameworks */,
|
9FAE4ACE29379A5A00772766 /* KeychainSwift in Frameworks */,
|
||||||
|
@ -311,8 +394,8 @@
|
||||||
9FD542E72962D2FF0045321A /* Lists in Frameworks */,
|
9FD542E72962D2FF0045321A /* Lists in Frameworks */,
|
||||||
9F398AAB2935FFDB00A889F2 /* Models in Frameworks */,
|
9F398AAB2935FFDB00A889F2 /* Models in Frameworks */,
|
||||||
9F5E581929545BE700A53960 /* Env in Frameworks */,
|
9F5E581929545BE700A53960 /* Env in Frameworks */,
|
||||||
9F2A540A29699705009B2D7C /* ReceiptParser in Frameworks */,
|
|
||||||
DA0B24FB2A6876D50045BDD7 /* SFSafeSymbols in Frameworks */,
|
DA0B24FB2A6876D50045BDD7 /* SFSafeSymbols in Frameworks */,
|
||||||
|
9FE6A42E2BD043A90055D388 /* RevenueCat in Frameworks */,
|
||||||
9F295540292B6C3400E0E81B /* Timeline in Frameworks */,
|
9F295540292B6C3400E0E81B /* Timeline in Frameworks */,
|
||||||
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */,
|
9F35DB4A29506FA100B3281A /* Notifications in Frameworks */,
|
||||||
9FC2A38B2B49D19A00DFD1C1 /* StatusKit in Frameworks */,
|
9FC2A38B2B49D19A00DFD1C1 /* StatusKit in Frameworks */,
|
||||||
|
@ -351,6 +434,22 @@
|
||||||
path = IceCubesNotifications;
|
path = IceCubesNotifications;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9F37BDD92BE36E08007F28AD /* IceCubesAppIntents */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9F7788E72BE65533004E6BEF /* AppAccountEntity.swift */,
|
||||||
|
9F37BDDC2BE37193007F28AD /* AppIntentService.swift */,
|
||||||
|
9F37BDE22BE393A7007F28AD /* AppShortcuts.swift */,
|
||||||
|
9F7788BF2BE63935004E6BEF /* InlinePostIntent.swift */,
|
||||||
|
9F37BDE02BE38646007F28AD /* PostImageIntent.swift */,
|
||||||
|
9F37BDDA2BE36E22007F28AD /* PostIntent.swift */,
|
||||||
|
9F37BDDE2BE37C35007F28AD /* TabIntent.swift */,
|
||||||
|
9F7788EC2BE78D75004E6BEF /* TimelineFilterEntity.swift */,
|
||||||
|
9F5BE6252BF48FE10074387E /* ListEntity.swift */,
|
||||||
|
);
|
||||||
|
path = IceCubesAppIntents;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9F398AB429360A5800A889F2 /* App */ = {
|
9F398AB429360A5800A889F2 /* App */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -375,6 +474,15 @@
|
||||||
path = Resources;
|
path = Resources;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9F5BE6202BF48FB20074387E /* ListsWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9F5BE6212BF48FBA0074387E /* ListsWidget.swift */,
|
||||||
|
9F5BE6232BF48FC40074387E /* ListsWidgetConfiguration.swift */,
|
||||||
|
);
|
||||||
|
path = ListsWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9F654BF0299AC46200D27FA5 /* Report */ = {
|
9F654BF0299AC46200D27FA5 /* Report */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -392,6 +500,33 @@
|
||||||
path = Timeline;
|
path = Timeline;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9F7788CA2BE652B1004E6BEF /* IceCubesAppWidgetsExtension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9F8B920D2BF77DA8003D37A2 /* AccountWidget */,
|
||||||
|
9F5BE6202BF48FB20074387E /* ListsWidget */,
|
||||||
|
9FF2FB6B2BE8AE78001560CE /* MentionWidget */,
|
||||||
|
9FF2FB642BE7F7FA001560CE /* Shared */,
|
||||||
|
9FF2FB5D2BE7F559001560CE /* HashtagPostsWidget */,
|
||||||
|
9FF2FB5C2BE7F549001560CE /* LatestPostsWidget */,
|
||||||
|
9F7788D72BE652B2004E6BEF /* IceCubesAppWidgetsExtensionExtension.entitlements */,
|
||||||
|
9F7788CB2BE652B1004E6BEF /* IceCubesAppWidgetsExtensionBundle.swift */,
|
||||||
|
9F7788D12BE652B2004E6BEF /* Assets.xcassets */,
|
||||||
|
9F7788D32BE652B2004E6BEF /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = IceCubesAppWidgetsExtension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9F8B920D2BF77DA8003D37A2 /* AccountWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9F8B920E2BF77DB4003D37A2 /* AccountWidgetConfiguration.swift */,
|
||||||
|
9F8B92102BF77DBB003D37A2 /* AccountWidget.swift */,
|
||||||
|
9F8B92142BF77F05003D37A2 /* AccountWidgetView.swift */,
|
||||||
|
);
|
||||||
|
path = AccountWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9FA0D2AC29921C1F008A143B /* Embeds */ = {
|
9FA0D2AC29921C1F008A143B /* Embeds */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -456,9 +591,11 @@
|
||||||
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */,
|
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */,
|
||||||
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */,
|
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */,
|
||||||
9FBFE63B292A715500C250E9 /* IceCubesApp */,
|
9FBFE63B292A715500C250E9 /* IceCubesApp */,
|
||||||
|
9F37BDD92BE36E08007F28AD /* IceCubesAppIntents */,
|
||||||
E9DF41FD29830FEC0003AAD2 /* IceCubesActionExtension */,
|
E9DF41FD29830FEC0003AAD2 /* IceCubesActionExtension */,
|
||||||
9F2A5417296AB631009B2D7C /* IceCubesNotifications */,
|
9F2A5417296AB631009B2D7C /* IceCubesNotifications */,
|
||||||
9FAD858929743F7400496AB1 /* IceCubesShareExtension */,
|
9FAD858929743F7400496AB1 /* IceCubesShareExtension */,
|
||||||
|
9F7788CA2BE652B1004E6BEF /* IceCubesAppWidgetsExtension */,
|
||||||
9FBFE63A292A715500C250E9 /* Products */,
|
9FBFE63A292A715500C250E9 /* Products */,
|
||||||
9FBFE64C292A72BD00C250E9 /* Frameworks */,
|
9FBFE64C292A72BD00C250E9 /* Frameworks */,
|
||||||
9FE3DB55296FEF5800628CB0 /* AppAccount */,
|
9FE3DB55296FEF5800628CB0 /* AppAccount */,
|
||||||
|
@ -484,6 +621,7 @@
|
||||||
9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */,
|
9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */,
|
||||||
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */,
|
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */,
|
||||||
E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */,
|
E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */,
|
||||||
|
9F7788C52BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -496,7 +634,6 @@
|
||||||
9FAE4AC8293774FF00772766 /* Info.plist */,
|
9FAE4AC8293774FF00772766 /* Info.plist */,
|
||||||
9F398AB429360A5800A889F2 /* App */,
|
9F398AB429360A5800A889F2 /* App */,
|
||||||
9F398AB529360A6100A889F2 /* Resources */,
|
9F398AB529360A6100A889F2 /* Resources */,
|
||||||
9FAD85822971BF7200496AB1 /* Secret.plist */,
|
|
||||||
);
|
);
|
||||||
path = IceCubesApp;
|
path = IceCubesApp;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -509,6 +646,8 @@
|
||||||
9F7335EE29674F7100AFF0BA /* QuickLook.framework */,
|
9F7335EE29674F7100AFF0BA /* QuickLook.framework */,
|
||||||
9F7335EB2967461B00AFF0BA /* AVKit.framework */,
|
9F7335EB2967461B00AFF0BA /* AVKit.framework */,
|
||||||
E9DF41FB29830FEC0003AAD2 /* UniformTypeIdentifiers.framework */,
|
E9DF41FB29830FEC0003AAD2 /* UniformTypeIdentifiers.framework */,
|
||||||
|
9F7788C62BE652B1004E6BEF /* WidgetKit.framework */,
|
||||||
|
9F7788C82BE652B1004E6BEF /* SwiftUI.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -538,6 +677,42 @@
|
||||||
path = Settings;
|
path = Settings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9FF2FB5C2BE7F549001560CE /* LatestPostsWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9F7788CD2BE652B1004E6BEF /* LatestPostsWidget.swift */,
|
||||||
|
9F7788CF2BE652B1004E6BEF /* LatestPostsWidgetConfiguration.swift */,
|
||||||
|
);
|
||||||
|
path = LatestPostsWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9FF2FB5D2BE7F559001560CE /* HashtagPostsWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9FF2FB5E2BE7F56F001560CE /* HashtagPostsWidgetConfiguration.swift */,
|
||||||
|
9FF2FB602BE7F5A7001560CE /* HashtagPostsWidget.swift */,
|
||||||
|
);
|
||||||
|
path = HashtagPostsWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9FF2FB642BE7F7FA001560CE /* Shared */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9FF2FB652BE7F805001560CE /* PostsWidgetView.swift */,
|
||||||
|
9FF2FB682BE7F842001560CE /* SharedUtils.swift */,
|
||||||
|
);
|
||||||
|
path = Shared;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9FF2FB6B2BE8AE78001560CE /* MentionWidget */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9FF2FB6C2BE8AE90001560CE /* MentionWidget.swift */,
|
||||||
|
9FF2FB6E2BE8AE9B001560CE /* MentionWidgetConfiguration.swift */,
|
||||||
|
);
|
||||||
|
path = MentionWidget;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E9B576C029743F2A00BCE646 /* Localization */ = {
|
E9B576C029743F2A00BCE646 /* Localization */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -589,6 +764,31 @@
|
||||||
productReference = 9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */;
|
productReference = 9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */;
|
||||||
productType = "com.apple.product-type.app-extension";
|
productType = "com.apple.product-type.app-extension";
|
||||||
};
|
};
|
||||||
|
9F7788C42BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 9F7788D82BE652B2004E6BEF /* Build configuration list for PBXNativeTarget "IceCubesAppWidgetsExtensionExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
9F7788C12BE652B1004E6BEF /* Sources */,
|
||||||
|
9F7788C22BE652B1004E6BEF /* Frameworks */,
|
||||||
|
9F7788C32BE652B1004E6BEF /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = IceCubesAppWidgetsExtensionExtension;
|
||||||
|
packageProductDependencies = (
|
||||||
|
9F7788DD2BE6543D004E6BEF /* Account */,
|
||||||
|
9F7788DF2BE6543D004E6BEF /* AppAccount */,
|
||||||
|
9F7788E12BE6543D004E6BEF /* Env */,
|
||||||
|
9F7788E32BE6543D004E6BEF /* Models */,
|
||||||
|
9F7788E52BE6543D004E6BEF /* Network */,
|
||||||
|
9F7788EF2BE78E77004E6BEF /* Timeline */,
|
||||||
|
);
|
||||||
|
productName = IceCubesAppWidgetsExtensionExtension;
|
||||||
|
productReference = 9F7788C52BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
9FAD858729743F7400496AB1 /* IceCubesShareExtension */ = {
|
9FAD858729743F7400496AB1 /* IceCubesShareExtension */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 9FAD859329743F7400496AB1 /* Build configuration list for PBXNativeTarget "IceCubesShareExtension" */;
|
buildConfigurationList = 9FAD859329743F7400496AB1 /* Build configuration list for PBXNativeTarget "IceCubesShareExtension" */;
|
||||||
|
@ -631,6 +831,7 @@
|
||||||
9F2A541C296AB631009B2D7C /* PBXTargetDependency */,
|
9F2A541C296AB631009B2D7C /* PBXTargetDependency */,
|
||||||
9FAD859129743F7400496AB1 /* PBXTargetDependency */,
|
9FAD859129743F7400496AB1 /* PBXTargetDependency */,
|
||||||
E9DF420629830FEC0003AAD2 /* PBXTargetDependency */,
|
E9DF420629830FEC0003AAD2 /* PBXTargetDependency */,
|
||||||
|
9F7788D52BE652B2004E6BEF /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = IceCubesApp;
|
name = IceCubesApp;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
@ -644,12 +845,11 @@
|
||||||
9F55C68F2955993C00F94077 /* Explore */,
|
9F55C68F2955993C00F94077 /* Explore */,
|
||||||
9FD542E62962D2FF0045321A /* Lists */,
|
9FD542E62962D2FF0045321A /* Lists */,
|
||||||
9F7335E92966B3F800AFF0BA /* Conversations */,
|
9F7335E92966B3F800AFF0BA /* Conversations */,
|
||||||
9F2A540929699705009B2D7C /* ReceiptParser */,
|
|
||||||
9F2A540B29699705009B2D7C /* RevenueCat */,
|
|
||||||
9FE3DB56296FEFCA00628CB0 /* AppAccount */,
|
9FE3DB56296FEFCA00628CB0 /* AppAccount */,
|
||||||
DA0B24FA2A6876D50045BDD7 /* SFSafeSymbols */,
|
DA0B24FA2A6876D50045BDD7 /* SFSafeSymbols */,
|
||||||
9FC2A38A2B49D19A00DFD1C1 /* StatusKit */,
|
9FC2A38A2B49D19A00DFD1C1 /* StatusKit */,
|
||||||
9FE4CCAA2B4C848A00DA5F13 /* GiphyUISDK */,
|
9FE4CCAA2B4C848A00DA5F13 /* GiphyUISDK */,
|
||||||
|
9FE6A42D2BD043A90055D388 /* RevenueCat */,
|
||||||
);
|
);
|
||||||
productName = IceCubesApp;
|
productName = IceCubesApp;
|
||||||
productReference = 9FBFE639292A715500C250E9 /* Ice Cubes.app */;
|
productReference = 9FBFE639292A715500C250E9 /* Ice Cubes.app */;
|
||||||
|
@ -683,12 +883,15 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = 1;
|
BuildIndependentTargetsInParallel = 1;
|
||||||
LastSwiftUpdateCheck = 1420;
|
LastSwiftUpdateCheck = 1530;
|
||||||
LastUpgradeCheck = 1500;
|
LastUpgradeCheck = 1500;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
9F2A5415296AB631009B2D7C = {
|
9F2A5415296AB631009B2D7C = {
|
||||||
CreatedOnToolsVersion = 14.2;
|
CreatedOnToolsVersion = 14.2;
|
||||||
};
|
};
|
||||||
|
9F7788C42BE652B1004E6BEF = {
|
||||||
|
CreatedOnToolsVersion = 15.3;
|
||||||
|
};
|
||||||
9FAD858729743F7400496AB1 = {
|
9FAD858729743F7400496AB1 = {
|
||||||
CreatedOnToolsVersion = 14.2;
|
CreatedOnToolsVersion = 14.2;
|
||||||
};
|
};
|
||||||
|
@ -724,13 +927,14 @@
|
||||||
be,
|
be,
|
||||||
uk,
|
uk,
|
||||||
"zh-Hant",
|
"zh-Hant",
|
||||||
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = 9FBFE630292A715500C250E9;
|
mainGroup = 9FBFE630292A715500C250E9;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
9FAE4ACC29379A5A00772766 /* XCRemoteSwiftPackageReference "keychain-swift" */,
|
9FAE4ACC29379A5A00772766 /* XCRemoteSwiftPackageReference "keychain-swift" */,
|
||||||
9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */,
|
|
||||||
DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */,
|
DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */,
|
||||||
9FE4CCA92B4C848A00DA5F13 /* XCRemoteSwiftPackageReference "giphy-ios-sdk" */,
|
9FE4CCA92B4C848A00DA5F13 /* XCRemoteSwiftPackageReference "giphy-ios-sdk" */,
|
||||||
|
9FE6A42C2BD043A80055D388 /* XCRemoteSwiftPackageReference "purchases-ios" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 9FBFE63A292A715500C250E9 /* Products */;
|
productRefGroup = 9FBFE63A292A715500C250E9 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
@ -740,6 +944,7 @@
|
||||||
E9DF41F929830FEC0003AAD2 /* IceCubesActionExtension */,
|
E9DF41F929830FEC0003AAD2 /* IceCubesActionExtension */,
|
||||||
9F2A5415296AB631009B2D7C /* IceCubesNotifications */,
|
9F2A5415296AB631009B2D7C /* IceCubesNotifications */,
|
||||||
9FAD858729743F7400496AB1 /* IceCubesShareExtension */,
|
9FAD858729743F7400496AB1 /* IceCubesShareExtension */,
|
||||||
|
9F7788C42BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
@ -755,6 +960,14 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
9F7788C32BE652B1004E6BEF /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
9F7788D22BE652B2004E6BEF /* Assets.xcassets in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
9FAD858629743F7400496AB1 /* Resources */ = {
|
9FAD858629743F7400496AB1 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -778,7 +991,6 @@
|
||||||
9F18801829AE477F00D85459 /* favorite.wav in Resources */,
|
9F18801829AE477F00D85459 /* favorite.wav in Resources */,
|
||||||
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */,
|
9F24EEB829360C330042359D /* Preview Assets.xcassets in Resources */,
|
||||||
069709A8298C87B5006E4CB5 /* OpenDyslexic-Regular.otf in Resources */,
|
069709A8298C87B5006E4CB5 /* OpenDyslexic-Regular.otf in Resources */,
|
||||||
9FAD85832971BF7200496AB1 /* Secret.plist in Resources */,
|
|
||||||
9F18801229AE477F00D85459 /* tabSelection.wav in Resources */,
|
9F18801229AE477F00D85459 /* tabSelection.wav in Resources */,
|
||||||
9F18801429AE477F00D85459 /* bookmark.wav in Resources */,
|
9F18801429AE477F00D85459 /* bookmark.wav in Resources */,
|
||||||
9F18801629AE477F00D85459 /* refresh.wav in Resources */,
|
9F18801629AE477F00D85459 /* refresh.wav in Resources */,
|
||||||
|
@ -809,6 +1021,30 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
9F7788C12BE652B1004E6BEF /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
9F5BE6272BF492CF0074387E /* ListEntity.swift in Sources */,
|
||||||
|
9FF2FB622BE7F5D5001560CE /* HashtagPostsWidget.swift in Sources */,
|
||||||
|
9FF2FB712BE8AEA0001560CE /* MentionWidget.swift in Sources */,
|
||||||
|
9F8B92162BF77F0B003D37A2 /* AccountWidgetView.swift in Sources */,
|
||||||
|
9F8B92122BF77DBE003D37A2 /* AccountWidgetConfiguration.swift in Sources */,
|
||||||
|
9F8B92132BF77DBE003D37A2 /* AccountWidget.swift in Sources */,
|
||||||
|
9F7788EA2BE65585004E6BEF /* AppAccountEntity.swift in Sources */,
|
||||||
|
9FF2FB6A2BE7F84E001560CE /* SharedUtils.swift in Sources */,
|
||||||
|
9F7788CE2BE652B1004E6BEF /* LatestPostsWidget.swift in Sources */,
|
||||||
|
9F7788EE2BE78D7B004E6BEF /* TimelineFilterEntity.swift in Sources */,
|
||||||
|
9F5BE6292BF492D40074387E /* ListsWidget.swift in Sources */,
|
||||||
|
9F7788CC2BE652B1004E6BEF /* IceCubesAppWidgetsExtensionBundle.swift in Sources */,
|
||||||
|
9FF2FB702BE8AE9D001560CE /* MentionWidgetConfiguration.swift in Sources */,
|
||||||
|
9F7788D02BE652B1004E6BEF /* LatestPostsWidgetConfiguration.swift in Sources */,
|
||||||
|
9FF2FB672BE7F816001560CE /* PostsWidgetView.swift in Sources */,
|
||||||
|
9FF2FB632BE7F5D9001560CE /* HashtagPostsWidgetConfiguration.swift in Sources */,
|
||||||
|
9F5BE6282BF492D10074387E /* ListsWidgetConfiguration.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
9FAD858429743F7400496AB1 /* Sources */ = {
|
9FAD858429743F7400496AB1 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -830,6 +1066,11 @@
|
||||||
9F15D6042B3DC2180008C220 /* NavigationSheet.swift in Sources */,
|
9F15D6042B3DC2180008C220 /* NavigationSheet.swift in Sources */,
|
||||||
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */,
|
9FA6FD6229C04A8800E2312C /* TranslationSettingsView.swift in Sources */,
|
||||||
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */,
|
9F35DB4C2952005C00B3281A /* MessagesTab.swift in Sources */,
|
||||||
|
9F37BDDB2BE36E22007F28AD /* PostIntent.swift in Sources */,
|
||||||
|
9F37BDDD2BE37193007F28AD /* AppIntentService.swift in Sources */,
|
||||||
|
9F37BDE12BE38646007F28AD /* PostImageIntent.swift in Sources */,
|
||||||
|
9F37BDDF2BE37C35007F28AD /* TabIntent.swift in Sources */,
|
||||||
|
9F7788C02BE63935004E6BEF /* InlinePostIntent.swift in Sources */,
|
||||||
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */,
|
9FAD85CF2975B68900496AB1 /* SideBarView.swift in Sources */,
|
||||||
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
9FAE4ACB293783B000772766 /* SettingsTab.swift in Sources */,
|
||||||
9FC14EF42B494D940006CEE1 /* RemoteTimelinesSettingView.swift in Sources */,
|
9FC14EF42B494D940006CEE1 /* RemoteTimelinesSettingView.swift in Sources */,
|
||||||
|
@ -848,9 +1089,12 @@
|
||||||
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */,
|
9F2B92FA295DA7D700DE16D0 /* AddAccountsView.swift in Sources */,
|
||||||
639CDF9C296AC82F00C35E58 /* SafariRouter.swift in Sources */,
|
639CDF9C296AC82F00C35E58 /* SafariRouter.swift in Sources */,
|
||||||
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
|
9F35DB4729506F6600B3281A /* NotificationTab.swift in Sources */,
|
||||||
|
9F7788ED2BE78D75004E6BEF /* TimelineFilterEntity.swift in Sources */,
|
||||||
|
9F37BDE32BE393A7007F28AD /* AppShortcuts.swift in Sources */,
|
||||||
9F654BEF299AC45B00D27FA5 /* ReportView.swift in Sources */,
|
9F654BEF299AC45B00D27FA5 /* ReportView.swift in Sources */,
|
||||||
D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */,
|
D08A9C3529956CFA00204A4A /* SwipeActionsSettingsView.swift in Sources */,
|
||||||
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */,
|
9F7335F22967608F00AFF0BA /* AddRemoteTimelineView.swift in Sources */,
|
||||||
|
9F7788E82BE65533004E6BEF /* AppAccountEntity.swift in Sources */,
|
||||||
9FC14EF62B494DFF0006CEE1 /* RecenTagsSettingView.swift in Sources */,
|
9FC14EF62B494DFF0006CEE1 /* RecenTagsSettingView.swift in Sources */,
|
||||||
9F6028562B3F36AE00476078 /* AppView.swift in Sources */,
|
9F6028562B3F36AE00476078 /* AppView.swift in Sources */,
|
||||||
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
9F55C68D2955968700F94077 /* ExploreTab.swift in Sources */,
|
||||||
|
@ -877,6 +1121,15 @@
|
||||||
target = 9F2A5415296AB631009B2D7C /* IceCubesNotifications */;
|
target = 9F2A5415296AB631009B2D7C /* IceCubesNotifications */;
|
||||||
targetProxy = 9F2A541B296AB631009B2D7C /* PBXContainerItemProxy */;
|
targetProxy = 9F2A541B296AB631009B2D7C /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
9F7788D52BE652B2004E6BEF /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
platformFilters = (
|
||||||
|
ios,
|
||||||
|
maccatalyst,
|
||||||
|
);
|
||||||
|
target = 9F7788C42BE652B1004E6BEF /* IceCubesAppWidgetsExtensionExtension */;
|
||||||
|
targetProxy = 9F7788D42BE652B2004E6BEF /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
9FAD859129743F7400496AB1 /* PBXTargetDependency */ = {
|
9FAD859129743F7400496AB1 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
platformFilters = (
|
platformFilters = (
|
||||||
|
@ -940,7 +1193,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -975,7 +1228,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -991,6 +1244,78 @@
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
9F7788D92BE652B2004E6BEF /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = IceCubesAppWidgetsExtension/IceCubesAppWidgetsExtensionExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 730;
|
||||||
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = IceCubesAppWidgetsExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = IceCubesAppWidgetsExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 17.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.10.44;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesAppWidgetsExtension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
9F7788DA2BE652B2004E6BEF /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = IceCubesAppWidgetsExtension/IceCubesAppWidgetsExtensionExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 730;
|
||||||
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = IceCubesAppWidgetsExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = IceCubesAppWidgetsExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 17.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.10.44;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesAppWidgetsExtension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
9FAD859429743F7400496AB1 /* Debug */ = {
|
9FAD859429743F7400496AB1 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
@ -1011,7 +1336,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -1045,7 +1370,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -1066,7 +1391,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = NO;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
@ -1132,7 +1457,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = NO;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
@ -1189,10 +1514,11 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIconAlternate0 AppIconAlternate6 AppIconAlternate7 AppIconAlternate8 AppIconAlternate10 AppIconAlternate11 AppIconAlternate12 AppIconAlternate13 AppIconAlternate14 AppIconAlternate15 AppIconAlternate16 AppIconAlternate17 AppIconAlternate19 AppIconAlternate18 AppIconAlternate20 AppIconAlternate21 AppIconAlternate22 AppIconAlternate23 AppIconAlternate24 AppIconAlternate25 AppIconAlternate26 AppIconAlternate27 AppIconAlternate28 AppIconAlternate29 AppIconAlternate30 AppIconAlternate31 AppIconAlternate32 AppIconAlternate33 AppIconAlternate34 AppIconAlternate35 AppIconAlternate36 AppIconAlternate37 AppIconAlternate38 AppIconAlternate39 AppIconAlternate40 AppIconAlternate42 AppIconAlternate2 AppIconAlternate41 AppIconAlternate45 AppIconAlternate44 AppIconAlternate1 AppIconAlternate4 AppIconAlternate3 AppIconAlternate5 AppIconAlternate9 AppIconAlternate43";
|
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIconAlternate0 AppIconAlternate6 AppIconAlternate7 AppIconAlternate8 AppIconAlternate10 AppIconAlternate11 AppIconAlternate12 AppIconAlternate13 AppIconAlternate14 AppIconAlternate15 AppIconAlternate16 AppIconAlternate17 AppIconAlternate19 AppIconAlternate18 AppIconAlternate20 AppIconAlternate21 AppIconAlternate22 AppIconAlternate23 AppIconAlternate24 AppIconAlternate25 AppIconAlternate26 AppIconAlternate27 AppIconAlternate28 AppIconAlternate29 AppIconAlternate30 AppIconAlternate31 AppIconAlternate32 AppIconAlternate33 AppIconAlternate34 AppIconAlternate35 AppIconAlternate36 AppIconAlternate37 AppIconAlternate38 AppIconAlternate39 AppIconAlternate40 AppIconAlternate42 AppIconAlternate2 AppIconAlternate41 AppIconAlternate45 AppIconAlternate44 AppIconAlternate1 AppIconAlternate4 AppIconAlternate3 AppIconAlternate5 AppIconAlternate46 AppIconAlternate9 AppIconAlternate43";
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = NO;
|
||||||
CODE_SIGN_ENTITLEMENTS = IceCubesApp/App/IceCubesApp.entitlements;
|
CODE_SIGN_ENTITLEMENTS = IceCubesApp/App/IceCubesApp.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "-";
|
CODE_SIGN_IDENTITY = "-";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||||
|
@ -1208,7 +1534,8 @@
|
||||||
INFOPLIST_FILE = IceCubesApp/Info.plist;
|
INFOPLIST_FILE = IceCubesApp/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "Ice Cubes";
|
INFOPLIST_KEY_CFBundleDisplayName = "Ice Cubes";
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to Mastodon";
|
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to attach to your Mastodon posts.";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "© 2024 Thomas Ricouard";
|
||||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
|
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||||
|
@ -1225,7 +1552,7 @@
|
||||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
|
||||||
PRODUCT_NAME = "Ice Cubes";
|
PRODUCT_NAME = "Ice Cubes";
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
|
@ -1243,10 +1570,11 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIconAlternate0 AppIconAlternate6 AppIconAlternate7 AppIconAlternate8 AppIconAlternate10 AppIconAlternate11 AppIconAlternate12 AppIconAlternate13 AppIconAlternate14 AppIconAlternate15 AppIconAlternate16 AppIconAlternate17 AppIconAlternate19 AppIconAlternate18 AppIconAlternate20 AppIconAlternate21 AppIconAlternate22 AppIconAlternate23 AppIconAlternate24 AppIconAlternate25 AppIconAlternate26 AppIconAlternate27 AppIconAlternate28 AppIconAlternate29 AppIconAlternate30 AppIconAlternate31 AppIconAlternate32 AppIconAlternate33 AppIconAlternate34 AppIconAlternate35 AppIconAlternate36 AppIconAlternate37 AppIconAlternate38 AppIconAlternate39 AppIconAlternate40 AppIconAlternate42 AppIconAlternate2 AppIconAlternate41 AppIconAlternate45 AppIconAlternate44 AppIconAlternate1 AppIconAlternate4 AppIconAlternate3 AppIconAlternate5 AppIconAlternate9 AppIconAlternate43";
|
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "AppIconAlternate0 AppIconAlternate6 AppIconAlternate7 AppIconAlternate8 AppIconAlternate10 AppIconAlternate11 AppIconAlternate12 AppIconAlternate13 AppIconAlternate14 AppIconAlternate15 AppIconAlternate16 AppIconAlternate17 AppIconAlternate19 AppIconAlternate18 AppIconAlternate20 AppIconAlternate21 AppIconAlternate22 AppIconAlternate23 AppIconAlternate24 AppIconAlternate25 AppIconAlternate26 AppIconAlternate27 AppIconAlternate28 AppIconAlternate29 AppIconAlternate30 AppIconAlternate31 AppIconAlternate32 AppIconAlternate33 AppIconAlternate34 AppIconAlternate35 AppIconAlternate36 AppIconAlternate37 AppIconAlternate38 AppIconAlternate39 AppIconAlternate40 AppIconAlternate42 AppIconAlternate2 AppIconAlternate41 AppIconAlternate45 AppIconAlternate44 AppIconAlternate1 AppIconAlternate4 AppIconAlternate3 AppIconAlternate5 AppIconAlternate46 AppIconAlternate9 AppIconAlternate43";
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = NO;
|
||||||
CODE_SIGN_ENTITLEMENTS = "IceCubesApp/App/IceCubesApp-release.entitlements";
|
CODE_SIGN_ENTITLEMENTS = "IceCubesApp/App/IceCubesApp-release.entitlements";
|
||||||
CODE_SIGN_IDENTITY = "-";
|
CODE_SIGN_IDENTITY = "-";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||||
|
@ -1262,7 +1590,8 @@
|
||||||
INFOPLIST_FILE = IceCubesApp/Info.plist;
|
INFOPLIST_FILE = IceCubesApp/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "Ice Cubes";
|
INFOPLIST_KEY_CFBundleDisplayName = "Ice Cubes";
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to Mastodon";
|
INFOPLIST_KEY_NSCameraUsageDescription = "Upload photos & videos to attach to your Mastodon posts.";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "© 2024 Thomas Ricouard";
|
||||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
|
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "Upload photos & videos to Mastodon";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||||
|
@ -1279,7 +1608,7 @@
|
||||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
|
||||||
PRODUCT_NAME = "Ice Cubes";
|
PRODUCT_NAME = "Ice Cubes";
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
|
@ -1314,7 +1643,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -1349,7 +1678,7 @@
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.10.22;
|
MARKETING_VERSION = 1.10.44;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
@ -1376,6 +1705,15 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
9F7788D82BE652B2004E6BEF /* Build configuration list for PBXNativeTarget "IceCubesAppWidgetsExtensionExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
9F7788D92BE652B2004E6BEF /* Debug */,
|
||||||
|
9F7788DA2BE652B2004E6BEF /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
9FAD859329743F7400496AB1 /* Build configuration list for PBXNativeTarget "IceCubesShareExtension" */ = {
|
9FAD859329743F7400496AB1 /* Build configuration list for PBXNativeTarget "IceCubesShareExtension" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
@ -1415,14 +1753,6 @@
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/RevenueCat/purchases-ios.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 4.0.0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
9FAE4ACC29379A5A00772766 /* XCRemoteSwiftPackageReference "keychain-swift" */ = {
|
9FAE4ACC29379A5A00772766 /* XCRemoteSwiftPackageReference "keychain-swift" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/evgenyneu/keychain-swift";
|
repositoryURL = "https://github.com/evgenyneu/keychain-swift";
|
||||||
|
@ -1436,7 +1766,15 @@
|
||||||
repositoryURL = "https://github.com/Giphy/giphy-ios-sdk";
|
repositoryURL = "https://github.com/Giphy/giphy-ios-sdk";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
kind = upToNextMajorVersion;
|
||||||
minimumVersion = 2.2.7;
|
minimumVersion = 2.2.8;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
9FE6A42C2BD043A80055D388 /* XCRemoteSwiftPackageReference "purchases-ios" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/RevenueCat/purchases-ios";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 4.40.1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
|
DA0B24F92A6876D40045BDD7 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
|
||||||
|
@ -1454,16 +1792,6 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Timeline;
|
productName = Timeline;
|
||||||
};
|
};
|
||||||
9F2A540929699705009B2D7C /* ReceiptParser */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */;
|
|
||||||
productName = ReceiptParser;
|
|
||||||
};
|
|
||||||
9F2A540B29699705009B2D7C /* RevenueCat */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 9F2A540829699705009B2D7C /* XCRemoteSwiftPackageReference "purchases-ios" */;
|
|
||||||
productName = RevenueCat;
|
|
||||||
};
|
|
||||||
9F2A5423296AB67A009B2D7C /* Env */ = {
|
9F2A5423296AB67A009B2D7C /* Env */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Env;
|
productName = Env;
|
||||||
|
@ -1501,6 +1829,30 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Conversations;
|
productName = Conversations;
|
||||||
};
|
};
|
||||||
|
9F7788DD2BE6543D004E6BEF /* Account */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Account;
|
||||||
|
};
|
||||||
|
9F7788DF2BE6543D004E6BEF /* AppAccount */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = AppAccount;
|
||||||
|
};
|
||||||
|
9F7788E12BE6543D004E6BEF /* Env */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Env;
|
||||||
|
};
|
||||||
|
9F7788E32BE6543D004E6BEF /* Models */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Models;
|
||||||
|
};
|
||||||
|
9F7788E52BE6543D004E6BEF /* Network */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Network;
|
||||||
|
};
|
||||||
|
9F7788EF2BE78E77004E6BEF /* Timeline */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Timeline;
|
||||||
|
};
|
||||||
9F7D93932980063100EE6B7A /* AppAccount */ = {
|
9F7D93932980063100EE6B7A /* AppAccount */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = AppAccount;
|
productName = AppAccount;
|
||||||
|
@ -1569,6 +1921,11 @@
|
||||||
package = 9FE4CCA92B4C848A00DA5F13 /* XCRemoteSwiftPackageReference "giphy-ios-sdk" */;
|
package = 9FE4CCA92B4C848A00DA5F13 /* XCRemoteSwiftPackageReference "giphy-ios-sdk" */;
|
||||||
productName = GiphyUISDK;
|
productName = GiphyUISDK;
|
||||||
};
|
};
|
||||||
|
9FE6A42D2BD043A90055D388 /* RevenueCat */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 9FE6A42C2BD043A80055D388 /* XCRemoteSwiftPackageReference "purchases-ios" */;
|
||||||
|
productName = RevenueCat;
|
||||||
|
};
|
||||||
9FFF677B299B7B2C00FE700A /* Notifications */ = {
|
9FFF677B299B7B2C00FE700A /* Notifications */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Notifications;
|
productName = Notifications;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/mergesort/Bodega",
|
"location" : "https://github.com/mergesort/Bodega",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "f0554077c178088ba11557bbdbb71775cc6a1b84",
|
"revision" : "bfd8871e9c2590d31b200e54c75428a71483afdf",
|
||||||
"version" : "2.1.0"
|
"version" : "2.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -14,8 +14,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/Dean151/ButtonKit",
|
"location" : "https://github.com/Dean151/ButtonKit",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "377f5bab4ed047704316d531e0826d4de5ebf6a4",
|
"revision" : "9e44e960106bd222ca26ddc1e8d85df36229cc40",
|
||||||
"version" : "0.1.1"
|
"version" : "0.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/divadretlaw/EmojiText",
|
"location" : "https://github.com/divadretlaw/EmojiText",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "d0664390e3236ff6241ea0586d80f4e92702973b",
|
"revision" : "174a7bc7bd75650ad1acb5679dbb754296093de0",
|
||||||
"version" : "3.2.1"
|
"version" : "4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -32,8 +32,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/Giphy/giphy-ios-sdk",
|
"location" : "https://github.com/Giphy/giphy-ios-sdk",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "95c32b862185e76107841b49bfff8ff7230f3b68",
|
"revision" : "16cbb3368f77e73735abc3d9b15871d1e6c120cc",
|
||||||
"version" : "2.2.7"
|
"version" : "2.2.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
"location" : "https://github.com/evgenyneu/keychain-swift",
|
"location" : "https://github.com/evgenyneu/keychain-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"branch" : "master",
|
"branch" : "master",
|
||||||
"revision" : "f38cb0ada97847ac5068b915b8d2793b35435668"
|
"revision" : "5e1b02b6a9dac2a759a1d5dbc175c86bd192a608"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -59,8 +59,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/nicklockwood/LRUCache",
|
"location" : "https://github.com/nicklockwood/LRUCache",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "6d2b5246c9c98dcd498552bb22f08d55b12a8371",
|
"revision" : "542f0449556327415409ededc9c43a4bd0a397dc",
|
||||||
"version" : "1.0.4"
|
"version" : "1.0.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -68,17 +68,17 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/kean/Nuke",
|
"location" : "https://github.com/kean/Nuke",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "1694798e876113d44f6ec6ead965d7286695981d",
|
"revision" : "311016d972aa751ae8ab0cd5897422ebe7db0501",
|
||||||
"version" : "12.2.0"
|
"version" : "12.7.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identity" : "purchases-ios",
|
"identity" : "purchases-ios",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/RevenueCat/purchases-ios.git",
|
"location" : "https://github.com/RevenueCat/purchases-ios",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "b8d20ba1c8e13cc73d72e37cf98607d01fd357b6",
|
"revision" : "7ec1091a6f929c40be2a1c695a63471f5d0c330d",
|
||||||
"version" : "4.31.2"
|
"version" : "4.43.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -95,8 +95,26 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/stephencelis/SQLite.swift.git",
|
"location" : "https://github.com/stephencelis/SQLite.swift.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "7a2e3cd27de56f6d396e84f63beefd0267b55ccb",
|
"revision" : "a95fc6df17d108bd99210db5e8a9bac90fe984b8",
|
||||||
"version" : "0.14.1"
|
"version" : "0.15.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-cmark",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-cmark.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "f218e5d7691f78b55bfa39b367763f4612486c35",
|
||||||
|
"version" : "0.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-markdown",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-markdown",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "e4f95e2dc23097a1a9a1dfdfe3fe3ee44de77378",
|
||||||
|
"version" : "0.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -104,26 +122,17 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/scinfu/SwiftSoup.git",
|
"location" : "https://github.com/scinfu/SwiftSoup.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "8b6cf29eead8841a1fa7822481cb3af4ddaadba6",
|
"revision" : "028487d4a8a291b2fe1b4392b5425b6172056148",
|
||||||
"version" : "2.6.1"
|
"version" : "2.7.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"identity" : "swiftui-introspect",
|
"identity" : "swiftui-introspect",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/siteline/SwiftUI-Introspect.git",
|
"location" : "https://github.com/siteline/swiftui-introspect",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "9e1cc02a65b22e09a8251261cccbccce02731fc5",
|
"revision" : "668a65735751432b640260c56dfa621cec568368",
|
||||||
"version" : "1.1.1"
|
"version" : "1.2.0"
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swiftui-shimmer",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/markiv/SwiftUI-Shimmer",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "965a7cbcbf094cbcf22b9251a2323bdc3432e171",
|
|
||||||
"version" : "1.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1530"
|
||||||
|
wasCreatedForAppExtension = "YES"
|
||||||
|
version = "2.0">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "9F7788C42BE652B1004E6BEF"
|
||||||
|
BuildableName = "IceCubesAppWidgetsExtensionExtension.appex"
|
||||||
|
BlueprintName = "IceCubesAppWidgetsExtensionExtension"
|
||||||
|
ReferencedContainer = "container:IceCubesApp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "9FBFE638292A715500C250E9"
|
||||||
|
BuildableName = "Ice Cubes.app"
|
||||||
|
BlueprintName = "IceCubesApp"
|
||||||
|
ReferencedContainer = "container:IceCubesApp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = ""
|
||||||
|
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||||
|
launchStyle = "0"
|
||||||
|
askForAppToLaunch = "Yes"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES"
|
||||||
|
launchAutomaticallySubstyle = "2">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "9FBFE638292A715500C250E9"
|
||||||
|
BuildableName = "Ice Cubes.app"
|
||||||
|
BlueprintName = "IceCubesApp"
|
||||||
|
ReferencedContainer = "container:IceCubesApp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<EnvironmentVariables>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "_XCWidgetKind"
|
||||||
|
value = ""
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "_XCWidgetDefaultView"
|
||||||
|
value = "timeline"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
<EnvironmentVariable
|
||||||
|
key = "_XCWidgetFamily"
|
||||||
|
value = "systemMedium"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</EnvironmentVariable>
|
||||||
|
</EnvironmentVariables>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
askForAppToLaunch = "Yes"
|
||||||
|
launchAutomaticallySubstyle = "2">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "9FBFE638292A715500C250E9"
|
||||||
|
BuildableName = "Ice Cubes.app"
|
||||||
|
BlueprintName = "IceCubesApp"
|
||||||
|
ReferencedContainer = "container:IceCubesApp.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -8,6 +8,7 @@ import LinkPresentation
|
||||||
import Lists
|
import Lists
|
||||||
import MediaUI
|
import MediaUI
|
||||||
import Models
|
import Models
|
||||||
|
import Notifications
|
||||||
import StatusKit
|
import StatusKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Timeline
|
import Timeline
|
||||||
|
@ -60,9 +61,19 @@ extension View {
|
||||||
scrollToTopSignal: .constant(0),
|
scrollToTopSignal: .constant(0),
|
||||||
canFilterTimeline: false)
|
canFilterTimeline: false)
|
||||||
case let .trendingLinks(cards):
|
case let .trendingLinks(cards):
|
||||||
CardsListView(cards: cards)
|
TrendingLinksListView(cards: cards)
|
||||||
case let .tagsList(tags):
|
case let .tagsList(tags):
|
||||||
TagsListView(tags: tags)
|
TagsListView(tags: tags)
|
||||||
|
case .notificationsRequests:
|
||||||
|
NotificationsRequestsListView()
|
||||||
|
case let .notificationForAccount(accountId):
|
||||||
|
NotificationsListView(lockedType: nil,
|
||||||
|
lockedAccountId: accountId,
|
||||||
|
scrollToTopSignal: .constant(0))
|
||||||
|
case .blockedAccounts:
|
||||||
|
AccountsListView(mode: .blocked)
|
||||||
|
case .mutedAccounts:
|
||||||
|
AccountsListView(mode: .muted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +85,13 @@ extension View {
|
||||||
StatusEditor.MainView(mode: .replyTo(status: status))
|
StatusEditor.MainView(mode: .replyTo(status: status))
|
||||||
.withEnvironments()
|
.withEnvironments()
|
||||||
case let .newStatusEditor(visibility):
|
case let .newStatusEditor(visibility):
|
||||||
StatusEditor.MainView(mode: .new(visibility: visibility))
|
StatusEditor.MainView(mode: .new(text: nil, visibility: visibility))
|
||||||
|
.withEnvironments()
|
||||||
|
case let .prefilledStatusEditor(text, visibility):
|
||||||
|
StatusEditor.MainView(mode: .new(text: text, visibility: visibility))
|
||||||
|
.withEnvironments()
|
||||||
|
case let .imageURL(urls, visibility):
|
||||||
|
StatusEditor.MainView(mode: .imageURL(urls: urls, visibility: visibility))
|
||||||
.withEnvironments()
|
.withEnvironments()
|
||||||
case let .editStatusEditor(status):
|
case let .editStatusEditor(status):
|
||||||
StatusEditor.MainView(mode: .edit(status: status))
|
StatusEditor.MainView(mode: .edit(status: status))
|
||||||
|
@ -82,6 +99,9 @@ extension View {
|
||||||
case let .quoteStatusEditor(status):
|
case let .quoteStatusEditor(status):
|
||||||
StatusEditor.MainView(mode: .quote(status: status))
|
StatusEditor.MainView(mode: .quote(status: status))
|
||||||
.withEnvironments()
|
.withEnvironments()
|
||||||
|
case let .quoteLinkStatusEditor(link):
|
||||||
|
StatusEditor.MainView(mode: .quoteLink(link: link))
|
||||||
|
.withEnvironments()
|
||||||
case let .mentionStatusEditor(account, visibility):
|
case let .mentionStatusEditor(account, visibility):
|
||||||
StatusEditor.MainView(mode: .mention(account: account, visibility: visibility))
|
StatusEditor.MainView(mode: .mention(account: account, visibility: visibility))
|
||||||
.withEnvironments()
|
.withEnvironments()
|
||||||
|
@ -135,6 +155,13 @@ extension View {
|
||||||
case .timelineContentFilter:
|
case .timelineContentFilter:
|
||||||
NavigationSheet { TimelineContentFilterView() }
|
NavigationSheet { TimelineContentFilterView() }
|
||||||
.presentationDetents([.medium])
|
.presentationDetents([.medium])
|
||||||
|
.presentationBackground(.thinMaterial)
|
||||||
|
.withEnvironments()
|
||||||
|
case .accountEditInfo:
|
||||||
|
EditAccountView()
|
||||||
|
.withEnvironments()
|
||||||
|
case .accountFiltersList:
|
||||||
|
FiltersListView()
|
||||||
.withEnvironments()
|
.withEnvironments()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ struct AppView: View {
|
||||||
@Environment(Theme.self) private var theme
|
@Environment(Theme.self) private var theme
|
||||||
@Environment(StreamWatcher.self) private var watcher
|
@Environment(StreamWatcher.self) private var watcher
|
||||||
|
|
||||||
|
@Environment(\.openWindow) var openWindow
|
||||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
|
|
||||||
|
|
||||||
@Binding var selectedTab: Tab
|
@Binding var selectedTab: Tab
|
||||||
@Binding var appRouterPath: RouterPath
|
@Binding var appRouterPath: RouterPath
|
||||||
|
|
||||||
|
@ -57,7 +57,11 @@ struct AppView: View {
|
||||||
selectedTab
|
selectedTab
|
||||||
}, set: { newTab in
|
}, set: { newTab in
|
||||||
if newTab == .post {
|
if newTab == .post {
|
||||||
|
#if os(visionOS)
|
||||||
|
openWindow(value: WindowDestinationEditor.newStatusEditor(visibility: userPreferences.postVisibility))
|
||||||
|
#else
|
||||||
appRouterPath.presentedSheet = .newStatusEditor(visibility: userPreferences.postVisibility)
|
appRouterPath.presentedSheet = .newStatusEditor(visibility: userPreferences.postVisibility)
|
||||||
|
#endif
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if newTab == selectedTab {
|
if newTab == selectedTab {
|
||||||
|
@ -85,7 +89,7 @@ struct AppView: View {
|
||||||
}
|
}
|
||||||
.tag(tab)
|
.tag(tab)
|
||||||
.badge(badgeFor(tab: tab))
|
.badge(badgeFor(tab: tab))
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .tabBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .tabBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.id(appAccountsManager.currentClient.id)
|
.id(appAccountsManager.currentClient.id)
|
||||||
|
@ -118,7 +122,7 @@ struct AppView: View {
|
||||||
.tag(tab)
|
.tag(tab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.introspect(.tabView, on: .iOS(.v17)) { (tabview: UITabBarController) in
|
.introspect(.tabView, on: .iOS(.v17, .v18)) { (tabview: UITabBarController) in
|
||||||
tabview.tabBar.isHidden = horizontalSizeClass == .regular
|
tabview.tabBar.isHidden = horizontalSizeClass == .regular
|
||||||
tabview.customizableViewControllers = []
|
tabview.customizableViewControllers = []
|
||||||
tabview.moreNavigationController.isNavigationBarHidden = true
|
tabview.moreNavigationController.isNavigationBarHidden = true
|
||||||
|
|
|
@ -4,6 +4,12 @@ import SwiftUI
|
||||||
extension IceCubesApp {
|
extension IceCubesApp {
|
||||||
@CommandsBuilder
|
@CommandsBuilder
|
||||||
var appMenu: some Commands {
|
var appMenu: some Commands {
|
||||||
|
CommandGroup(replacing: .appSettings) {
|
||||||
|
Button("menu.settings") {
|
||||||
|
appRouterPath.presentedSheet = .settings
|
||||||
|
}
|
||||||
|
.keyboardShortcut(",", modifiers: .command)
|
||||||
|
}
|
||||||
CommandGroup(replacing: .newItem) {
|
CommandGroup(replacing: .newItem) {
|
||||||
Button("menu.new-window") {
|
Button("menu.new-window") {
|
||||||
openWindow(id: "MainWindow")
|
openWindow(id: "MainWindow")
|
||||||
|
@ -54,5 +60,11 @@ extension IceCubesApp {
|
||||||
}
|
}
|
||||||
.keyboardShortcut("l", modifiers: .shift)
|
.keyboardShortcut("l", modifiers: .shift)
|
||||||
}
|
}
|
||||||
|
CommandGroup(replacing: .help) {
|
||||||
|
Button("menu.help.github") {
|
||||||
|
let url = URL(string: "https://github.com/Dimillian/IceCubesApp/issues")!
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import AppIntents
|
||||||
import Env
|
import Env
|
||||||
import MediaUI
|
import MediaUI
|
||||||
import StatusKit
|
import StatusKit
|
||||||
|
@ -22,6 +23,7 @@ extension IceCubesApp {
|
||||||
.environment(theme)
|
.environment(theme)
|
||||||
.environment(watcher)
|
.environment(watcher)
|
||||||
.environment(pushNotificationsService)
|
.environment(pushNotificationsService)
|
||||||
|
.environment(appIntentService)
|
||||||
.environment(\.isSupporter, isSupporter)
|
.environment(\.isSupporter, isSupporter)
|
||||||
.sheet(item: $quickLook.selectedMediaAttachment) { selectedMediaAttachment in
|
.sheet(item: $quickLook.selectedMediaAttachment) { selectedMediaAttachment in
|
||||||
MediaUIView(selectedAttachment: selectedMediaAttachment,
|
MediaUIView(selectedAttachment: selectedMediaAttachment,
|
||||||
|
@ -47,6 +49,12 @@ extension IceCubesApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onChange(of: appIntentService.handledIntent) { _, _ in
|
||||||
|
if let intent = appIntentService.handledIntent?.intent {
|
||||||
|
handleIntent(intent)
|
||||||
|
appIntentService.handledIntent = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
.withModelContainer()
|
.withModelContainer()
|
||||||
}
|
}
|
||||||
#if targetEnvironment(macCatalyst)
|
#if targetEnvironment(macCatalyst)
|
||||||
|
@ -74,7 +82,9 @@ extension IceCubesApp {
|
||||||
Group {
|
Group {
|
||||||
switch destination.wrappedValue {
|
switch destination.wrappedValue {
|
||||||
case let .newStatusEditor(visibility):
|
case let .newStatusEditor(visibility):
|
||||||
StatusEditor.MainView(mode: .new(visibility: visibility))
|
StatusEditor.MainView(mode: .new(text: nil, visibility: visibility))
|
||||||
|
case let .prefilledStatusEditor(text, visibility):
|
||||||
|
StatusEditor.MainView(mode: .new(text: text, visibility: visibility))
|
||||||
case let .editStatusEditor(status):
|
case let .editStatusEditor(status):
|
||||||
StatusEditor.MainView(mode: .edit(status: status))
|
StatusEditor.MainView(mode: .edit(status: status))
|
||||||
case let .quoteStatusEditor(status):
|
case let .quoteStatusEditor(status):
|
||||||
|
@ -83,11 +93,14 @@ extension IceCubesApp {
|
||||||
StatusEditor.MainView(mode: .replyTo(status: status))
|
StatusEditor.MainView(mode: .replyTo(status: status))
|
||||||
case let .mentionStatusEditor(account, visibility):
|
case let .mentionStatusEditor(account, visibility):
|
||||||
StatusEditor.MainView(mode: .mention(account: account, visibility: visibility))
|
StatusEditor.MainView(mode: .mention(account: account, visibility: visibility))
|
||||||
|
case let .quoteLinkStatusEditor(link):
|
||||||
|
StatusEditor.MainView(mode: .quoteLink(link: link))
|
||||||
case .none:
|
case .none:
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.withEnvironments()
|
.withEnvironments()
|
||||||
|
.environment(RouterPath())
|
||||||
.withModelContainer()
|
.withModelContainer()
|
||||||
.applyTheme(theme)
|
.applyTheme(theme)
|
||||||
.frame(minWidth: 300, minHeight: 400)
|
.frame(minWidth: 300, minHeight: 400)
|
||||||
|
@ -113,4 +126,23 @@ extension IceCubesApp {
|
||||||
.defaultSize(width: 1200, height: 1000)
|
.defaultSize(width: 1200, height: 1000)
|
||||||
.windowResizability(.contentMinSize)
|
.windowResizability(.contentMinSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleIntent(_: any AppIntent) {
|
||||||
|
if let postIntent = appIntentService.handledIntent?.intent as? PostIntent {
|
||||||
|
#if os(visionOS) || os(macOS)
|
||||||
|
openWindow(value: WindowDestinationEditor.prefilledStatusEditor(text: postIntent.content ?? "",
|
||||||
|
visibility: userPreferences.postVisibility))
|
||||||
|
#else
|
||||||
|
appRouterPath.presentedSheet = .prefilledStatusEditor(text: postIntent.content ?? "",
|
||||||
|
visibility: userPreferences.postVisibility)
|
||||||
|
#endif
|
||||||
|
} else if let tabIntent = appIntentService.handledIntent?.intent as? TabIntent {
|
||||||
|
selectedTab = tabIntent.tab.toAppTab
|
||||||
|
} else if let imageIntent = appIntentService.handledIntent?.intent as? PostImageIntent,
|
||||||
|
let urls = imageIntent.images?.compactMap({ $0.fileURL })
|
||||||
|
{
|
||||||
|
appRouterPath.presentedSheet = .imageURL(urls: urls,
|
||||||
|
visibility: userPreferences.postVisibility)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct IceCubesApp: App {
|
||||||
@State var currentAccount = CurrentAccount.shared
|
@State var currentAccount = CurrentAccount.shared
|
||||||
@State var userPreferences = UserPreferences.shared
|
@State var userPreferences = UserPreferences.shared
|
||||||
@State var pushNotificationsService = PushNotificationsService.shared
|
@State var pushNotificationsService = PushNotificationsService.shared
|
||||||
|
@State var appIntentService = AppIntentService.shared
|
||||||
@State var watcher = StreamWatcher.shared
|
@State var watcher = StreamWatcher.shared
|
||||||
@State var quickLook = QuickLook.shared
|
@State var quickLook = QuickLook.shared
|
||||||
@State var theme = Theme.shared
|
@State var theme = Theme.shared
|
||||||
|
@ -79,7 +80,7 @@ struct IceCubesApp: App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppDelegate: NSObject, UIApplicationDelegate {
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
func application(_: UIApplication,
|
func application(_: UIApplication,
|
||||||
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool
|
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool
|
||||||
{
|
{
|
||||||
|
@ -113,4 +114,11 @@ class AppDelegate: NSObject, UIApplicationDelegate {
|
||||||
}
|
}
|
||||||
return configuration
|
return configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func buildMenu(with builder: UIMenuBuilder) {
|
||||||
|
super.buildMenu(with: builder)
|
||||||
|
builder.remove(menu: .document)
|
||||||
|
builder.remove(menu: .toolbar)
|
||||||
|
builder.remove(menu: .sidebar)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,13 +65,7 @@ public struct ReportView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
CancelToolbarItem()
|
||||||
Button {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Text("action.cancel")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ extension View {
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
private struct SafariRouter: ViewModifier {
|
private struct SafariRouter: ViewModifier {
|
||||||
|
@Environment(\.isSecondaryColumn) private var isSecondaryColumn: Bool
|
||||||
@Environment(Theme.self) private var theme
|
@Environment(Theme.self) private var theme
|
||||||
@Environment(UserPreferences.self) private var preferences
|
@Environment(UserPreferences.self) private var preferences
|
||||||
@Environment(RouterPath.self) private var routerPath
|
@Environment(RouterPath.self) private var routerPath
|
||||||
|
@ -25,13 +26,15 @@ private struct SafariRouter: ViewModifier {
|
||||||
content
|
content
|
||||||
.environment(\.openURL, OpenURLAction { url in
|
.environment(\.openURL, OpenURLAction { url in
|
||||||
// Open internal URL.
|
// Open internal URL.
|
||||||
routerPath.handle(url: url)
|
guard !isSecondaryColumn else { return .discarded }
|
||||||
|
return routerPath.handle(url: url)
|
||||||
})
|
})
|
||||||
.onOpenURL { url in
|
.onOpenURL { url in
|
||||||
// Open external URL (from icecubesapp://)
|
// Open external URL (from icecubesapp://)
|
||||||
|
guard !isSecondaryColumn else { return }
|
||||||
let urlString = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "https://")
|
let urlString = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "https://")
|
||||||
guard let url = URL(string: urlString), url.host != nil else { return }
|
guard let url = URL(string: urlString), url.host != nil else { return }
|
||||||
_ = routerPath.handle(url: url)
|
_ = routerPath.handleDeepLink(url: url)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
routerPath.urlHandler = { url in
|
routerPath.urlHandler = { url in
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct SideBarView<Content: View>: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func makeIconForTab(tab: Tab) -> some View {
|
private func makeIconForTab(tab: Tab) -> some View {
|
||||||
|
HStack {
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topTrailing) {
|
||||||
SideBarIcon(systemIconName: tab.iconName,
|
SideBarIcon(systemIconName: tab.iconName,
|
||||||
isSelected: tab == selectedTab)
|
isSelected: tab == selectedTab)
|
||||||
|
@ -43,8 +44,16 @@ struct SideBarView<Content: View>: View {
|
||||||
makeBadgeView(count: badge)
|
makeBadgeView(count: badge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
if userPreferences.isSidebarExpanded {
|
||||||
.frame(width: .sidebarWidth, height: 50)
|
Text(tab.title)
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor(tab == selectedTab ? theme.tintColor : theme.labelColor)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(width: (userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth) - 24, height: 50)
|
||||||
|
.background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear,
|
||||||
|
in: RoundedRectangle(cornerRadius: 8))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func makeBadgeView(count: Int) -> some View {
|
private func makeBadgeView(count: Int) -> some View {
|
||||||
|
@ -74,6 +83,7 @@ struct SideBarView<Content: View>: View {
|
||||||
.offset(x: 2, y: -2)
|
.offset(x: 2, y: -2)
|
||||||
}
|
}
|
||||||
.buttonStyle(.borderedProminent)
|
.buttonStyle(.borderedProminent)
|
||||||
|
.help(Tab.post.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func makeAccountButton(account: AppAccount, showBadge: Bool) -> some View {
|
private func makeAccountButton(account: AppAccount, showBadge: Bool) -> some View {
|
||||||
|
@ -90,9 +100,19 @@ struct SideBarView<Content: View>: View {
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topTrailing) {
|
||||||
AppAccountView(viewModel: .init(appAccount: account, isCompact: true),
|
if userPreferences.isSidebarExpanded {
|
||||||
|
AppAccountView(viewModel: .init(appAccount: account,
|
||||||
|
isCompact: false,
|
||||||
|
isInSettings: false),
|
||||||
isParentPresented: .constant(false))
|
isParentPresented: .constant(false))
|
||||||
if showBadge,
|
} else {
|
||||||
|
AppAccountView(viewModel: .init(appAccount: account,
|
||||||
|
isCompact: true,
|
||||||
|
isInSettings: false),
|
||||||
|
isParentPresented: .constant(false))
|
||||||
|
}
|
||||||
|
if !userPreferences.isSidebarExpanded,
|
||||||
|
showBadge,
|
||||||
let token = account.oauthToken,
|
let token = account.oauthToken,
|
||||||
let notificationsCount = userPreferences.notificationsCount[token],
|
let notificationsCount = userPreferences.notificationsCount[token],
|
||||||
notificationsCount > 0
|
notificationsCount > 0
|
||||||
|
@ -100,13 +120,23 @@ struct SideBarView<Content: View>: View {
|
||||||
makeBadgeView(count: notificationsCount)
|
makeBadgeView(count: notificationsCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(.leading, userPreferences.isSidebarExpanded ? 16 : 0)
|
||||||
}
|
}
|
||||||
.frame(width: .sidebarWidth, height: 50)
|
.help(accountButtonTitle(accountName: account.accountName))
|
||||||
|
.frame(width: userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth, height: 50)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.background(selectedTab == .profile && account.id == appAccounts.currentAccount.id ?
|
.background(selectedTab == .profile && account.id == appAccounts.currentAccount.id ?
|
||||||
theme.secondaryBackgroundColor : .clear)
|
theme.secondaryBackgroundColor : .clear)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func accountButtonTitle(accountName: String?) -> LocalizedStringKey {
|
||||||
|
if let accountName {
|
||||||
|
"tab.profile-account-\(accountName)"
|
||||||
|
} else {
|
||||||
|
Tab.profile.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var tabsView: some View {
|
private var tabsView: some View {
|
||||||
ForEach(tabs) { tab in
|
ForEach(tabs) { tab in
|
||||||
if tab != .profile && sidebarTabs.isEnabled(tab) {
|
if tab != .profile && sidebarTabs.isEnabled(tab) {
|
||||||
|
@ -131,7 +161,7 @@ struct SideBarView<Content: View>: View {
|
||||||
} label: {
|
} label: {
|
||||||
makeIconForTab(tab: tab)
|
makeIconForTab(tab: tab)
|
||||||
}
|
}
|
||||||
.background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear)
|
.help(tab.title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,14 +183,26 @@ struct SideBarView<Content: View>: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postButton
|
|
||||||
.padding(.top, 12)
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: .sidebarWidth)
|
.frame(width: userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth)
|
||||||
.scrollContentBackground(.hidden)
|
.scrollContentBackground(.hidden)
|
||||||
.background(.thinMaterial)
|
.background(.thinMaterial)
|
||||||
|
.safeAreaInset(edge: .bottom, content: {
|
||||||
|
HStack(spacing: 16) {
|
||||||
|
postButton
|
||||||
|
.padding(.vertical, 24)
|
||||||
|
.padding(.leading, userPreferences.isSidebarExpanded ? 18 : 0)
|
||||||
|
if userPreferences.isSidebarExpanded {
|
||||||
|
Text("menu.new-post")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(theme.labelColor)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(width: userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth)
|
||||||
|
.background(.thinMaterial)
|
||||||
|
})
|
||||||
Divider().edgesIgnoringSafeArea(.all)
|
Divider().edgesIgnoringSafeArea(.all)
|
||||||
}
|
}
|
||||||
content()
|
content()
|
||||||
|
@ -191,6 +233,7 @@ private struct SideBarIcon: View {
|
||||||
self.isHovered = isHovered
|
self.isHovered = isHovered
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(width: 50, height: 40)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import Env
|
||||||
import Explore
|
import Explore
|
||||||
import Models
|
import Models
|
||||||
import Network
|
import Network
|
||||||
import Shimmer
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
@ -22,7 +21,7 @@ struct ExploreTab: View {
|
||||||
ExploreView(scrollToTopSignal: $scrollToTopSignal)
|
ExploreView(scrollToTopSignal: $scrollToTopSignal)
|
||||||
.withAppRouter()
|
.withAppRouter()
|
||||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarTab(routerPath: $routerPath)
|
ToolbarTab(routerPath: $routerPath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import DesignSystem
|
||||||
import Env
|
import Env
|
||||||
import Models
|
import Models
|
||||||
import Network
|
import Network
|
||||||
import Shimmer
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
@ -27,7 +26,7 @@ struct MessagesTab: View {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarTab(routerPath: $routerPath)
|
ToolbarTab(routerPath: $routerPath)
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.id(client.id)
|
.id(client.id)
|
||||||
}
|
}
|
||||||
.onChange(of: $popToRootTab.wrappedValue) { _, newValue in
|
.onChange(of: $popToRootTab.wrappedValue) { _, newValue in
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import SwiftUI
|
|
||||||
import Env
|
|
||||||
import AppAccount
|
import AppAccount
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
import Env
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct NavigationSheet<Content: View>: View {
|
struct NavigationSheet<Content: View>: View {
|
||||||
|
@ -17,13 +17,7 @@ struct NavigationSheet<Content: View>: View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
content()
|
content()
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
CloseToolbarItem()
|
||||||
Button {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "xmark.circle")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import SwiftUI
|
|
||||||
import Env
|
|
||||||
import AppAccount
|
import AppAccount
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
import Env
|
||||||
import Network
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct NavigationTab<Content: View>: View {
|
struct NavigationTab<Content: View>: View {
|
||||||
|
@ -32,7 +32,7 @@ struct NavigationTab<Content: View>: View {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarTab(routerPath: $routerPath)
|
ToolbarTab(routerPath: $routerPath)
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.onChange(of: client.id) {
|
.onChange(of: client.id) {
|
||||||
routerPath.path = []
|
routerPath.path = []
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct NotificationsTab: View {
|
||||||
}
|
}
|
||||||
ToolbarTab(routerPath: $routerPath)
|
ToolbarTab(routerPath: $routerPath)
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.id(client.id)
|
.id(client.id)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
@ -60,9 +60,9 @@ struct NotificationsTab: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onChange(of: selectedTab, { _, newValue in
|
.onChange(of: selectedTab) { _, _ in
|
||||||
clearNotifications()
|
clearNotifications()
|
||||||
})
|
}
|
||||||
.onChange(of: pushNotificationsService.handledNotification) { _, newValue in
|
.onChange(of: pushNotificationsService.handledNotification) { _, newValue in
|
||||||
if let newValue, let type = newValue.notification.supportedType {
|
if let newValue, let type = newValue.notification.supportedType {
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import DesignSystem
|
||||||
import Env
|
import Env
|
||||||
import Models
|
import Models
|
||||||
import Network
|
import Network
|
||||||
import Shimmer
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
@ -24,7 +23,7 @@ struct ProfileTab: View {
|
||||||
AccountDetailView(account: account, scrollToTopSignal: $scrollToTopSignal)
|
AccountDetailView(account: account, scrollToTopSignal: $scrollToTopSignal)
|
||||||
.withAppRouter()
|
.withAppRouter()
|
||||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.id(account.id)
|
.id(account.id)
|
||||||
} else {
|
} else {
|
||||||
AccountDetailView(account: .placeholder(), scrollToTopSignal: $scrollToTopSignal)
|
AccountDetailView(account: .placeholder(), scrollToTopSignal: $scrollToTopSignal)
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct AboutView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
Section {
|
Section {
|
||||||
#if !targetEnvironment(macCatalyst)
|
#if !targetEnvironment(macCatalyst) && !os(visionOS)
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Image(uiImage: .init(named: "AppIconAlternate0")!)
|
Image(uiImage: .init(named: "AppIconAlternate0")!)
|
||||||
|
@ -57,7 +57,7 @@ struct AboutView: View {
|
||||||
Label("settings.support.terms-of-use", systemImage: "checkmark.shield")
|
Label("settings.support.terms-of-use", systemImage: "checkmark.shield")
|
||||||
}
|
}
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("\(versionNumber)©2023 Thomas Ricouard")
|
Text("\(versionNumber)© 2024 Thomas Ricouard")
|
||||||
}
|
}
|
||||||
#if !os(visionOS)
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
|
|
@ -17,9 +17,8 @@ struct AccountSettingsView: View {
|
||||||
@Environment(Theme.self) private var theme
|
@Environment(Theme.self) private var theme
|
||||||
@Environment(AppAccountsManager.self) private var appAccountsManager
|
@Environment(AppAccountsManager.self) private var appAccountsManager
|
||||||
@Environment(Client.self) private var client
|
@Environment(Client.self) private var client
|
||||||
|
@Environment(RouterPath.self) private var routerPath
|
||||||
|
|
||||||
@State private var isEditingAccount: Bool = false
|
|
||||||
@State private var isEditingFilters: Bool = false
|
|
||||||
@State private var cachedPostsCount: Int = 0
|
@State private var cachedPostsCount: Int = 0
|
||||||
@State private var timelineCache = TimelineCache()
|
@State private var timelineCache = TimelineCache()
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ struct AccountSettingsView: View {
|
||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
Button {
|
Button {
|
||||||
isEditingAccount = true
|
routerPath.presentedSheet = .accountEditInfo
|
||||||
} label: {
|
} label: {
|
||||||
Label("account.action.edit-info", systemImage: "pencil")
|
Label("account.action.edit-info", systemImage: "pencil")
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
@ -40,7 +39,7 @@ struct AccountSettingsView: View {
|
||||||
|
|
||||||
if currentInstance.isFiltersSupported {
|
if currentInstance.isFiltersSupported {
|
||||||
Button {
|
Button {
|
||||||
isEditingFilters = true
|
routerPath.presentedSheet = .accountFiltersList
|
||||||
} label: {
|
} label: {
|
||||||
Label("account.action.edit-filters", systemImage: "line.3.horizontal.decrease.circle")
|
Label("account.action.edit-filters", systemImage: "line.3.horizontal.decrease.circle")
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
@ -96,12 +95,6 @@ struct AccountSettingsView: View {
|
||||||
}
|
}
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $isEditingAccount, content: {
|
|
||||||
EditAccountView()
|
|
||||||
})
|
|
||||||
.sheet(isPresented: $isEditingFilters, content: {
|
|
||||||
FiltersListView()
|
|
||||||
})
|
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .principal) {
|
ToolbarItem(placement: .principal) {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
|
@ -6,15 +6,15 @@ import Models
|
||||||
import Network
|
import Network
|
||||||
import NukeUI
|
import NukeUI
|
||||||
import SafariServices
|
import SafariServices
|
||||||
import Shimmer
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import AuthenticationServices
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct AddAccountView: View {
|
struct AddAccountView: View {
|
||||||
|
@Environment(\.webAuthenticationSession) private var webAuthenticationSession
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
@Environment(\.openURL) private var openURL
|
@Environment(\.openURL) private var openURL
|
||||||
@Environment(\.webAuthenticationSession) private var webAuthenticationSession
|
|
||||||
|
|
||||||
@Environment(AppAccountsManager.self) private var appAccountsManager
|
@Environment(AppAccountsManager.self) private var appAccountsManager
|
||||||
@Environment(CurrentAccount.self) private var currentAccount
|
@Environment(CurrentAccount.self) private var currentAccount
|
||||||
|
@ -89,9 +89,7 @@ struct AddAccountView: View {
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if !appAccountsManager.availableAccounts.isEmpty {
|
if !appAccountsManager.availableAccounts.isEmpty {
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
CancelToolbarItem()
|
||||||
Button("action.cancel", action: { dismiss() })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
@ -265,7 +263,6 @@ struct AddAccountView: View {
|
||||||
}
|
}
|
||||||
.redacted(reason: .placeholder)
|
.redacted(reason: .placeholder)
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
.shimmering()
|
|
||||||
#if !os(visionOS)
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
#endif
|
#endif
|
||||||
|
@ -306,13 +303,3 @@ struct AddAccountView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SafariView: UIViewControllerRepresentable {
|
|
||||||
let url: URL
|
|
||||||
|
|
||||||
func makeUIViewController(context _: UIViewControllerRepresentableContext<SafariView>) -> SFSafariViewController {
|
|
||||||
SFSafariViewController(url: url)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUIViewController(_: SFSafariViewController, context _: UIViewControllerRepresentableContext<SafariView>) {}
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import Models
|
||||||
import Network
|
import Network
|
||||||
import NukeUI
|
import NukeUI
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import UserNotifications
|
|
||||||
import Timeline
|
import Timeline
|
||||||
|
import UserNotifications
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct ContentSettingsView: View {
|
struct ContentSettingsView: View {
|
||||||
|
@ -59,6 +59,7 @@ struct ContentSettingsView: View {
|
||||||
userPreferences.appAutoExpandMedia = userPreferences.autoExpandMedia
|
userPreferences.appAutoExpandMedia = userPreferences.autoExpandMedia
|
||||||
userPreferences.appDefaultPostsSensitive = userPreferences.postIsSensitive
|
userPreferences.appDefaultPostsSensitive = userPreferences.postIsSensitive
|
||||||
userPreferences.appDefaultPostVisibility = userPreferences.postVisibility
|
userPreferences.appDefaultPostVisibility = userPreferences.postVisibility
|
||||||
|
userPreferences.appRequireAltText = userPreferences.appRequireAltText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +113,10 @@ struct ContentSettingsView: View {
|
||||||
Text("settings.content.default-sensitive")
|
Text("settings.content.default-sensitive")
|
||||||
}
|
}
|
||||||
.disabled(userPreferences.useInstanceContentSettings)
|
.disabled(userPreferences.useInstanceContentSettings)
|
||||||
|
|
||||||
|
Toggle(isOn: $userPreferences.appRequireAltText) {
|
||||||
|
Text("settings.content.require-alt-text")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if !os(visionOS)
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Observation
|
||||||
import StatusKit
|
import StatusKit
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
@MainActor
|
||||||
@Observable class DisplaySettingsLocalValues {
|
@Observable class DisplaySettingsLocalValues {
|
||||||
var tintColor = Theme.shared.tintColor
|
var tintColor = Theme.shared.tintColor
|
||||||
var primaryBackgroundColor = Theme.shared.primaryBackgroundColor
|
var primaryBackgroundColor = Theme.shared.primaryBackgroundColor
|
||||||
|
@ -35,11 +36,13 @@ struct DisplaySettingsView: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
Form {
|
Form {
|
||||||
|
#if !os(visionOS)
|
||||||
StatusRowView(viewModel: previewStatusViewModel)
|
StatusRowView(viewModel: previewStatusViewModel)
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
.opacity(0)
|
.opacity(0)
|
||||||
.hidden()
|
.hidden()
|
||||||
themeSection
|
themeSection
|
||||||
|
#endif
|
||||||
fontSection
|
fontSection
|
||||||
layoutSection
|
layoutSection
|
||||||
platformsSection
|
platformsSection
|
||||||
|
@ -74,7 +77,9 @@ struct DisplaySettingsView: View {
|
||||||
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
do { try await Task.sleep(for: .microseconds(500)) } catch {}
|
||||||
theme.fontSizeScale = localValues.fontSizeScale
|
theme.fontSizeScale = localValues.fontSizeScale
|
||||||
}
|
}
|
||||||
|
#if !os(visionOS)
|
||||||
examplePost
|
examplePost
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct IconSelectorView: View {
|
||||||
case alt38
|
case alt38
|
||||||
case alt39, alt40, alt41, alt42, alt43
|
case alt39, alt40, alt41, alt42, alt43
|
||||||
case alt44, alt45
|
case alt44, alt45
|
||||||
|
case alt46
|
||||||
|
|
||||||
var appIconName: String {
|
var appIconName: String {
|
||||||
return "AppIconAlternate\(rawValue)"
|
return "AppIconAlternate\(rawValue)"
|
||||||
|
@ -39,7 +40,7 @@ struct IconSelectorView: View {
|
||||||
|
|
||||||
static let items = [
|
static let items = [
|
||||||
IconSelector(title: "settings.app.icon.official".localized, icons: [
|
IconSelector(title: "settings.app.icon.official".localized, icons: [
|
||||||
.primary, .alt1, .alt2, .alt3, .alt4,
|
.primary, .alt46, .alt1, .alt2, .alt3, .alt4,
|
||||||
.alt5, .alt6, .alt7, .alt8,
|
.alt5, .alt6, .alt7, .alt8,
|
||||||
.alt9, .alt10, .alt11, .alt12, .alt13, .alt14, .alt15,
|
.alt9, .alt10, .alt11, .alt12, .alt13, .alt14, .alt15,
|
||||||
.alt16, .alt17, .alt18, .alt19, .alt20, .alt21]),
|
.alt16, .alt17, .alt18, .alt19, .alt20, .alt21]),
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import SwiftUI
|
|
||||||
import SwiftData
|
|
||||||
import Models
|
|
||||||
import Env
|
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
import Env
|
||||||
|
import Models
|
||||||
|
import SwiftData
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
struct RecenTagsSettingView: View {
|
struct RecenTagsSettingView: View {
|
||||||
@Environment(\.modelContext) private var context
|
@Environment(\.modelContext) private var context
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import SwiftUI
|
|
||||||
import SwiftData
|
|
||||||
import Models
|
|
||||||
import Env
|
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
import Env
|
||||||
|
import Models
|
||||||
|
import SwiftData
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
struct RemoteTimelinesSettingView: View {
|
struct RemoteTimelinesSettingView: View {
|
||||||
@Environment(\.modelContext) private var context
|
@Environment(\.modelContext) private var context
|
||||||
|
|
|
@ -32,6 +32,8 @@ struct SettingsTabs: View {
|
||||||
|
|
||||||
let isModal: Bool
|
let isModal: Bool
|
||||||
|
|
||||||
|
@State private var startingPoint: SettingsStartingPoint? = nil
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack(path: $routerPath.path) {
|
NavigationStack(path: $routerPath.path) {
|
||||||
Form {
|
Form {
|
||||||
|
@ -47,7 +49,7 @@ struct SettingsTabs: View {
|
||||||
#endif
|
#endif
|
||||||
.navigationTitle(Text("settings.title"))
|
.navigationTitle(Text("settings.title"))
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if isModal {
|
if isModal {
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
|
@ -64,6 +66,32 @@ struct SettingsTabs: View {
|
||||||
}
|
}
|
||||||
.withAppRouter()
|
.withAppRouter()
|
||||||
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $routerPath.presentedSheet)
|
||||||
|
.onAppear {
|
||||||
|
startingPoint = RouterPath.settingsStartingPoint
|
||||||
|
RouterPath.settingsStartingPoint = nil
|
||||||
|
}
|
||||||
|
.navigationDestination(item: $startingPoint) { targetView in
|
||||||
|
switch targetView {
|
||||||
|
case .display:
|
||||||
|
DisplaySettingsView()
|
||||||
|
case .haptic:
|
||||||
|
HapticSettingsView()
|
||||||
|
case .remoteTimelines:
|
||||||
|
RemoteTimelinesSettingView()
|
||||||
|
case .tagGroups:
|
||||||
|
TagsGroupSettingView()
|
||||||
|
case .recentTags:
|
||||||
|
RecenTagsSettingView()
|
||||||
|
case .content:
|
||||||
|
ContentSettingsView()
|
||||||
|
case .swipeActions:
|
||||||
|
SwipeActionsSettingsView()
|
||||||
|
case .tabAndSidebarEntries:
|
||||||
|
EmptyView()
|
||||||
|
case .translation:
|
||||||
|
TranslationSettingsView()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
routerPath.client = client
|
routerPath.client = client
|
||||||
|
@ -236,10 +264,14 @@ struct SettingsTabs: View {
|
||||||
Text("settings.app.icon")
|
Text("settings.app.icon")
|
||||||
} icon: {
|
} icon: {
|
||||||
let icon = IconSelectorView.Icon(string: UIApplication.shared.alternateIconName ?? "AppIcon")
|
let icon = IconSelectorView.Icon(string: UIApplication.shared.alternateIconName ?? "AppIcon")
|
||||||
Image(uiImage: .init(named: icon.appIconName)!)
|
if let image: UIImage = .init(named: icon.appIconName) {
|
||||||
|
Image(uiImage: image)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 25, height: 25)
|
.frame(width: 25, height: 25)
|
||||||
.cornerRadius(4)
|
.cornerRadius(4)
|
||||||
|
} else {
|
||||||
|
EmptyView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,7 @@ import DesignSystem
|
||||||
import Env
|
import Env
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
@MainActor
|
||||||
struct SidebarEntriesSettingsView: View {
|
struct SidebarEntriesSettingsView: View {
|
||||||
@Environment(Theme.self) private var theme
|
@Environment(Theme.self) private var theme
|
||||||
@Environment(UserPreferences.self) private var userPreferences
|
@Environment(UserPreferences.self) private var userPreferences
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
import Env
|
import Env
|
||||||
import RevenueCat
|
import RevenueCat
|
||||||
import Shimmer
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
@ -280,6 +279,5 @@ struct SupportAppView: View {
|
||||||
}
|
}
|
||||||
.redacted(reason: .placeholder)
|
.redacted(reason: .placeholder)
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
.shimmering()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import SwiftUI
|
|
||||||
import SwiftData
|
|
||||||
import Models
|
|
||||||
import Env
|
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
import Env
|
||||||
|
import Models
|
||||||
|
import SwiftData
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
struct TagsGroupSettingView: View {
|
struct TagsGroupSettingView: View {
|
||||||
@Environment(\.modelContext) private var context
|
@Environment(\.modelContext) private var context
|
||||||
|
|
|
@ -11,16 +11,13 @@ struct TranslationSettingsView: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
deepLToggle
|
translationSelector
|
||||||
if preferences.alwaysUseDeepl {
|
if preferences.preferredTranslationType == .useDeepl {
|
||||||
Section("settings.translation.user-api-key") {
|
Section("settings.translation.user-api-key") {
|
||||||
deepLPicker
|
deepLPicker
|
||||||
SecureField("settings.translation.user-api-key", text: $apiKey)
|
SecureField("settings.translation.user-api-key", text: $apiKey)
|
||||||
.textContentType(.password)
|
.textContentType(.password)
|
||||||
}
|
}
|
||||||
.onAppear {
|
|
||||||
readValue()
|
|
||||||
}
|
|
||||||
#if !os(visionOS)
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +34,7 @@ struct TranslationSettingsView: View {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
backgroundAPIKey
|
||||||
autoDetectSection
|
autoDetectSection
|
||||||
}
|
}
|
||||||
.navigationTitle("settings.translation.navigation-title")
|
.navigationTitle("settings.translation.navigation-title")
|
||||||
|
@ -48,19 +46,39 @@ struct TranslationSettingsView: View {
|
||||||
writeNewValue()
|
writeNewValue()
|
||||||
}
|
}
|
||||||
.onAppear(perform: updatePrefs)
|
.onAppear(perform: updatePrefs)
|
||||||
|
.onAppear(perform: readValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var deepLToggle: some View {
|
private var translationSelector: some View {
|
||||||
@Bindable var preferences = preferences
|
@Bindable var preferences = preferences
|
||||||
Toggle(isOn: $preferences.alwaysUseDeepl) {
|
Picker("Translation Service", selection: $preferences.preferredTranslationType) {
|
||||||
Text("settings.translation.always-deepl")
|
ForEach(allTTCases, id: \.self) { type in
|
||||||
|
Text(type.description).tag(type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if !os(visionOS)
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var allTTCases: [TranslationType] {
|
||||||
|
TranslationType.allCases.filter { type in
|
||||||
|
if type != .useApple {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
#if canImport(_Translation_SwiftUI)
|
||||||
|
if #available(iOS 17.4, *) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return false
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var deepLPicker: some View {
|
private var deepLPicker: some View {
|
||||||
@Bindable var preferences = preferences
|
@Bindable var preferences = preferences
|
||||||
|
@ -80,6 +98,34 @@ struct TranslationSettingsView: View {
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("settings.translation.auto-detect-post-language-footer")
|
Text("settings.translation.auto-detect-post-language-footer")
|
||||||
}
|
}
|
||||||
|
#if !os(visionOS)
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var backgroundAPIKey: some View {
|
||||||
|
if preferences.preferredTranslationType != .useDeepl,
|
||||||
|
!apiKey.isEmpty
|
||||||
|
{
|
||||||
|
Section {
|
||||||
|
Text("The DeepL API Key is still stored!")
|
||||||
|
if preferences.preferredTranslationType == .useServerIfPossible {
|
||||||
|
Text("It can however still be used as a fallback for your instance's translation service.")
|
||||||
|
}
|
||||||
|
Button(role: .destructive) {
|
||||||
|
withAnimation {
|
||||||
|
writeNewValue(value: "")
|
||||||
|
readValue()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Text("action.delete")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if !os(visionOS)
|
||||||
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func writeNewValue() {
|
private func writeNewValue() {
|
||||||
|
@ -91,11 +137,7 @@ struct TranslationSettingsView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func readValue() {
|
private func readValue() {
|
||||||
if let apiKey = DeepLUserAPIHandler.readIfAllowed() {
|
apiKey = DeepLUserAPIHandler.readKey()
|
||||||
self.apiKey = apiKey
|
|
||||||
} else {
|
|
||||||
apiKey = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updatePrefs() {
|
private func updatePrefs() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Account
|
import Account
|
||||||
|
import AppIntents
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
import Explore
|
import Explore
|
||||||
import Foundation
|
import Foundation
|
||||||
|
@ -15,6 +16,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
|
||||||
case post
|
case post
|
||||||
case followedTags
|
case followedTags
|
||||||
case lists
|
case lists
|
||||||
|
case links
|
||||||
|
|
||||||
nonisolated var id: Int {
|
nonisolated var id: Int {
|
||||||
rawValue
|
rawValue
|
||||||
|
@ -25,7 +27,7 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func visionOSTab() -> [Tab] {
|
static func visionOSTab() -> [Tab] {
|
||||||
[.profile, .timeline, .notifications, .mentions, .explore, .messages, .settings]
|
[.profile, .timeline, .notifications, .mentions, .explore, .post, .settings]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
@ -67,6 +69,8 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
|
||||||
NavigationTab {
|
NavigationTab {
|
||||||
ListsListView()
|
ListsListView()
|
||||||
}
|
}
|
||||||
|
case .links:
|
||||||
|
NavigationTab { TrendingLinksListView(cards: []) }
|
||||||
case .post:
|
case .post:
|
||||||
VStack {}
|
VStack {}
|
||||||
case .other:
|
case .other:
|
||||||
|
@ -76,40 +80,47 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var label: some View {
|
var label: some View {
|
||||||
|
if self != .other {
|
||||||
|
Label(title, systemImage: iconName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var title: LocalizedStringKey {
|
||||||
switch self {
|
switch self {
|
||||||
case .timeline:
|
case .timeline:
|
||||||
Label("tab.timeline", systemImage: iconName)
|
"tab.timeline"
|
||||||
case .trending:
|
case .trending:
|
||||||
Label("tab.trending", systemImage: iconName)
|
"tab.trending"
|
||||||
case .local:
|
case .local:
|
||||||
Label("tab.local", systemImage: iconName)
|
"tab.local"
|
||||||
case .federated:
|
case .federated:
|
||||||
Label("tab.federated", systemImage: iconName)
|
"tab.federated"
|
||||||
case .notifications:
|
case .notifications:
|
||||||
Label("tab.notifications", systemImage: iconName)
|
"tab.notifications"
|
||||||
case .mentions:
|
case .mentions:
|
||||||
Label("tab.mentions", systemImage: iconName)
|
"tab.mentions"
|
||||||
case .explore:
|
case .explore:
|
||||||
Label("tab.explore", systemImage: iconName)
|
"tab.explore"
|
||||||
case .messages:
|
case .messages:
|
||||||
Label("tab.messages", systemImage: iconName)
|
"tab.messages"
|
||||||
case .settings:
|
case .settings:
|
||||||
Label("tab.settings", systemImage: iconName)
|
"tab.settings"
|
||||||
case .profile:
|
case .profile:
|
||||||
Label("tab.profile", systemImage: iconName)
|
"tab.profile"
|
||||||
case .bookmarks:
|
case .bookmarks:
|
||||||
Label("accessibility.tabs.profile.picker.bookmarks", systemImage: iconName)
|
"accessibility.tabs.profile.picker.bookmarks"
|
||||||
case .favorites:
|
case .favorites:
|
||||||
Label("accessibility.tabs.profile.picker.favorites", systemImage: iconName)
|
"accessibility.tabs.profile.picker.favorites"
|
||||||
case .post:
|
case .post:
|
||||||
Label("menu.new-post", systemImage: iconName)
|
"menu.new-post"
|
||||||
case .followedTags:
|
case .followedTags:
|
||||||
Label("timeline.filter.tags", systemImage: iconName)
|
"timeline.filter.tags"
|
||||||
case .lists:
|
case .lists:
|
||||||
Label("timeline.filter.lists", systemImage: iconName)
|
"timeline.filter.lists"
|
||||||
|
case .links:
|
||||||
|
"explore.section.trending.links"
|
||||||
case .other:
|
case .other:
|
||||||
EmptyView()
|
""
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +156,15 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
|
||||||
"tag"
|
"tag"
|
||||||
case .lists:
|
case .lists:
|
||||||
"list.bullet"
|
"list.bullet"
|
||||||
|
case .links:
|
||||||
|
"newspaper"
|
||||||
case .other:
|
case .other:
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
@Observable
|
@Observable
|
||||||
class SidebarTabs {
|
class SidebarTabs {
|
||||||
struct SidedebarTab: Hashable, Codable {
|
struct SidedebarTab: Hashable, Codable {
|
||||||
|
@ -196,6 +210,7 @@ class SidebarTabs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
@Observable
|
@Observable
|
||||||
class iOSTabs {
|
class iOSTabs {
|
||||||
enum TabEntries: String {
|
enum TabEntries: String {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import Models
|
||||||
import Network
|
import Network
|
||||||
import NukeUI
|
import NukeUI
|
||||||
import SFSafeSymbols
|
import SFSafeSymbols
|
||||||
import Shimmer
|
|
||||||
import SwiftData
|
import SwiftData
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
@ -39,7 +38,9 @@ struct EditTagGroupView: View {
|
||||||
focusedField: $focusedField
|
focusedField: $focusedField
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
#endif
|
||||||
|
|
||||||
Section("add-tag-groups.edit.tags") {
|
Section("add-tag-groups.edit.tags") {
|
||||||
TagsInputView(
|
TagsInputView(
|
||||||
|
@ -48,7 +49,9 @@ struct EditTagGroupView: View {
|
||||||
focusedField: $focusedField
|
focusedField: $focusedField
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
#if !os(visionOS)
|
||||||
.listRowBackground(theme.primaryBackgroundColor)
|
.listRowBackground(theme.primaryBackgroundColor)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
.formStyle(.grouped)
|
.formStyle(.grouped)
|
||||||
.navigationTitle(
|
.navigationTitle(
|
||||||
|
@ -63,9 +66,7 @@ struct EditTagGroupView: View {
|
||||||
.scrollDismissesKeyboard(.interactively)
|
.scrollDismissesKeyboard(.interactively)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
CancelToolbarItem()
|
||||||
Button("action.cancel", action: { dismiss() })
|
|
||||||
}
|
|
||||||
ToolbarItem(placement: .navigationBarTrailing) {
|
ToolbarItem(placement: .navigationBarTrailing) {
|
||||||
Button("action.save", action: { save() })
|
Button("action.save", action: { save() })
|
||||||
.disabled(!tagGroup.isValid)
|
.disabled(!tagGroup.isValid)
|
||||||
|
|
|
@ -4,7 +4,6 @@ import Env
|
||||||
import Models
|
import Models
|
||||||
import Network
|
import Network
|
||||||
import NukeUI
|
import NukeUI
|
||||||
import Shimmer
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
@ -58,9 +57,7 @@ struct AddRemoteTimelineView: View {
|
||||||
.scrollDismissesKeyboard(.immediately)
|
.scrollDismissesKeyboard(.immediately)
|
||||||
#endif
|
#endif
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
CancelToolbarItem()
|
||||||
Button("action.cancel", action: { dismiss() })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.onChange(of: instanceName) { _, newValue in
|
.onChange(of: instanceName) { _, newValue in
|
||||||
instanceNamePublisher.send(newValue)
|
instanceNamePublisher.send(newValue)
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct TimelineTab: View {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
toolbarView
|
toolbarView
|
||||||
}
|
}
|
||||||
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.50), for: .navigationBar)
|
.toolbarBackground(theme.primaryBackgroundColor.opacity(0.30), for: .navigationBar)
|
||||||
.id(client.id)
|
.id(client.id)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
@ -61,7 +61,7 @@ struct TimelineTab: View {
|
||||||
if client.isAuth {
|
if client.isAuth {
|
||||||
timeline = lastTimelineFilter
|
timeline = lastTimelineFilter
|
||||||
} else {
|
} else {
|
||||||
timeline = .federated
|
timeline = .trending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task {
|
Task {
|
||||||
|
@ -123,16 +123,16 @@ struct TimelineTab: View {
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var timelineFilterButton: some View {
|
private var timelineFilterButton: some View {
|
||||||
latestOrResumeButtons
|
headerGroup
|
||||||
contentFilterButton
|
|
||||||
Divider()
|
|
||||||
pinMenuButton
|
|
||||||
Divider()
|
|
||||||
timelineFiltersButtons
|
timelineFiltersButtons
|
||||||
|
if client.isAuth {
|
||||||
listsFiltersButons
|
listsFiltersButons
|
||||||
tagsFiltersButtons
|
tagsFiltersButtons
|
||||||
|
}
|
||||||
localTimelinesFiltersButtons
|
localTimelinesFiltersButtons
|
||||||
tagGroupsFiltersButtons
|
tagGroupsFiltersButtons
|
||||||
|
Divider()
|
||||||
|
contentFilterButton
|
||||||
}
|
}
|
||||||
|
|
||||||
private var addAccountButton: some View {
|
private var addAccountButton: some View {
|
||||||
|
@ -189,13 +189,15 @@ struct TimelineTab: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var latestOrResumeButtons: some View {
|
private var headerGroup: some View {
|
||||||
|
ControlGroup {
|
||||||
if timeline.supportNewestPagination {
|
if timeline.supportNewestPagination {
|
||||||
Button {
|
Button {
|
||||||
timeline = .latest
|
timeline = .latest
|
||||||
} label: {
|
} label: {
|
||||||
Label(TimelineFilter.latest.localizedTitle(), systemImage: TimelineFilter.latest.iconName())
|
Label(TimelineFilter.latest.localizedTitle(), systemImage: TimelineFilter.latest.iconName())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if timeline == .home {
|
if timeline == .home {
|
||||||
Button {
|
Button {
|
||||||
timeline = .resume
|
timeline = .resume
|
||||||
|
@ -206,11 +208,12 @@ struct TimelineTab: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pinButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var pinMenuButton: some View {
|
private var pinButton: some View {
|
||||||
let index = pinnedFilters.firstIndex(where: { $0.id == timeline.id })
|
let index = pinnedFilters.firstIndex(where: { $0.id == timeline.id })
|
||||||
Button {
|
Button {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
|
@ -324,7 +327,7 @@ struct TimelineTab: View {
|
||||||
if client.isAuth, canFilterTimeline {
|
if client.isAuth, canFilterTimeline {
|
||||||
timeline = lastTimelineFilter
|
timeline = lastTimelineFilter
|
||||||
} else if !client.isAuth {
|
} else if !client.isAuth {
|
||||||
timeline = .federated
|
timeline = .trending
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import SwiftUI
|
|
||||||
import Env
|
|
||||||
import AppAccount
|
import AppAccount
|
||||||
import DesignSystem
|
import DesignSystem
|
||||||
|
import Env
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct ToolbarTab: ToolbarContent {
|
struct ToolbarTab: ToolbarContent {
|
||||||
|
@ -9,17 +9,34 @@ struct ToolbarTab: ToolbarContent {
|
||||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||||
|
|
||||||
@Environment(UserPreferences.self) private var userPreferences
|
@Environment(UserPreferences.self) private var userPreferences
|
||||||
|
@Environment(Theme.self) private var theme
|
||||||
|
|
||||||
@Binding var routerPath: RouterPath
|
@Binding var routerPath: RouterPath
|
||||||
|
|
||||||
var body: some ToolbarContent {
|
var body: some ToolbarContent {
|
||||||
if !isSecondaryColumn {
|
if !isSecondaryColumn {
|
||||||
|
ToolbarItem(placement: .topBarLeading) {
|
||||||
|
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
|
||||||
|
Button {
|
||||||
|
withAnimation {
|
||||||
|
userPreferences.isSidebarExpanded.toggle()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
if userPreferences.isSidebarExpanded {
|
||||||
|
Image(systemName: "sidebar.squares.left")
|
||||||
|
} else {
|
||||||
|
Image(systemName: "sidebar.left")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
statusEditorToolbarItem(routerPath: routerPath,
|
statusEditorToolbarItem(routerPath: routerPath,
|
||||||
visibility: userPreferences.postVisibility)
|
visibility: userPreferences.postVisibility)
|
||||||
if UIDevice.current.userInterfaceIdiom != .pad ||
|
if UIDevice.current.userInterfaceIdiom != .pad ||
|
||||||
(UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact) {
|
(UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact)
|
||||||
|
{
|
||||||
ToolbarItem(placement: .navigationBarLeading) {
|
ToolbarItem(placement: .navigationBarLeading) {
|
||||||
AppAccountsSelectorView(routerPath: routerPath)
|
AppAccountsSelectorView(routerPath: routerPath, avatarConfig: theme.avatarShape == .circle ? .badge : .badgeRounded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/1024.png
Normal file
After Width: | Height: | Size: 991 KiB |
Before Width: | Height: | Size: 156 KiB |
|
@ -1,67 +1,67 @@
|
||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "AppIcon.png",
|
"filename" : "1024.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-16.png",
|
"filename" : "macos16.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "16x16"
|
"size" : "16x16"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-32.png",
|
"filename" : "macos32 1.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "16x16"
|
"size" : "16x16"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-32 1.png",
|
"filename" : "macos32.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "32x32"
|
"size" : "32x32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-64.png",
|
"filename" : "macos64.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "32x32"
|
"size" : "32x32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-128.png",
|
"filename" : "macos128.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "128x128"
|
"size" : "128x128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-256 1.png",
|
"filename" : "mac256 1.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "128x128"
|
"size" : "128x128"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-256.png",
|
"filename" : "mac256.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "256x256"
|
"size" : "256x256"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-512 1.png",
|
"filename" : "macOS512 1.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "256x256"
|
"size" : "256x256"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-512.png",
|
"filename" : "macOS512.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"size" : "512x512"
|
"size" : "512x512"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Icon-1024.png",
|
"filename" : "macOS1024.png",
|
||||||
"idiom" : "mac",
|
"idiom" : "mac",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"size" : "512x512"
|
"size" : "512x512"
|
||||||
|
|
Before Width: | Height: | Size: 501 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 734 B |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 5.5 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/mac256 1.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/mac256.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macOS1024.png
Normal file
After Width: | Height: | Size: 973 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macOS512 1.png
Normal file
After Width: | Height: | Size: 262 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macOS512.png
Normal file
After Width: | Height: | Size: 262 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macos128.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macos16.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macos32 1.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macos32.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
IceCubesApp/Assets.xcassets/AppIcon.appiconset/macos64.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 764 KiB |
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Back.png",
|
"filename" : "Background.png",
|
||||||
"idiom" : "vision",
|
"idiom" : "vision",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Front.png",
|
"filename" : "Layer 1.png",
|
||||||
"idiom" : "vision",
|
"idiom" : "vision",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 543 KiB |
After Width: | Height: | Size: 549 KiB |
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Middle.png",
|
|
||||||
"idiom" : "vision",
|
"idiom" : "vision",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 991 KiB |
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "AppIcon-fs8.png",
|
"filename" : "1024.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 156 KiB |
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "AppIcon-fs8.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
43
IceCubesAppIntents/AppAccountEntity.swift
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import AppAccount
|
||||||
|
import AppIntents
|
||||||
|
import Env
|
||||||
|
import Foundation
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
|
||||||
|
extension IntentDescription: @unchecked Sendable {}
|
||||||
|
extension TypeDisplayRepresentation: @unchecked Sendable {}
|
||||||
|
|
||||||
|
public struct AppAccountEntity: Identifiable, AppEntity {
|
||||||
|
public var id: String { account.id }
|
||||||
|
|
||||||
|
public let account: AppAccount
|
||||||
|
|
||||||
|
public static let defaultQuery = DefaultAppAccountEntityQuery()
|
||||||
|
|
||||||
|
public static let typeDisplayRepresentation: TypeDisplayRepresentation = "AppAccount"
|
||||||
|
|
||||||
|
public var displayRepresentation: DisplayRepresentation {
|
||||||
|
DisplayRepresentation(title: "\(account.accountName ?? account.server)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DefaultAppAccountEntityQuery: EntityQuery {
|
||||||
|
public init() {}
|
||||||
|
|
||||||
|
public func entities(for identifiers: [AppAccountEntity.ID]) async throws -> [AppAccountEntity] {
|
||||||
|
return await AppAccountsManager.shared.availableAccounts.filter { account in
|
||||||
|
identifiers.contains { id in
|
||||||
|
id == account.id
|
||||||
|
}
|
||||||
|
}.map { AppAccountEntity(account: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func suggestedEntities() async throws -> [AppAccountEntity] {
|
||||||
|
await AppAccountsManager.shared.availableAccounts.map { .init(account: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func defaultResult() async -> AppAccountEntity? {
|
||||||
|
await .init(account: AppAccountsManager.shared.currentAccount)
|
||||||
|
}
|
||||||
|
}
|
25
IceCubesAppIntents/AppIntentService.swift
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import AppIntents
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@Observable
|
||||||
|
public class AppIntentService: @unchecked Sendable {
|
||||||
|
struct HandledIntent: Equatable {
|
||||||
|
static func == (lhs: AppIntentService.HandledIntent, rhs: AppIntentService.HandledIntent) -> Bool {
|
||||||
|
lhs.id == rhs.id
|
||||||
|
}
|
||||||
|
|
||||||
|
let id: String
|
||||||
|
let intent: any AppIntent
|
||||||
|
|
||||||
|
init(intent: any AppIntent) {
|
||||||
|
id = UUID().uuidString
|
||||||
|
self.intent = intent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static let shared = AppIntentService()
|
||||||
|
|
||||||
|
var handledIntent: HandledIntent?
|
||||||
|
|
||||||
|
private init() {}
|
||||||
|
}
|
43
IceCubesAppIntents/AppShortcuts.swift
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import AppIntents
|
||||||
|
|
||||||
|
struct AppShortcuts: AppShortcutsProvider {
|
||||||
|
static var appShortcuts: [AppShortcut] {
|
||||||
|
AppShortcut(
|
||||||
|
intent: PostIntent(),
|
||||||
|
phrases: [
|
||||||
|
"Post in \(.applicationName)",
|
||||||
|
"Post a status on Mastodon with \(.applicationName)",
|
||||||
|
],
|
||||||
|
shortTitle: "Compose a post",
|
||||||
|
systemImageName: "square.and.pencil"
|
||||||
|
)
|
||||||
|
AppShortcut(
|
||||||
|
intent: InlinePostIntent(),
|
||||||
|
phrases: [
|
||||||
|
"Write a post with \(.applicationName)",
|
||||||
|
"Send on post on Mastodon with \(.applicationName)",
|
||||||
|
],
|
||||||
|
shortTitle: "Send a post",
|
||||||
|
systemImageName: "square.and.pencil"
|
||||||
|
)
|
||||||
|
AppShortcut(
|
||||||
|
intent: TabIntent(),
|
||||||
|
phrases: [
|
||||||
|
"Open \(.applicationName)",
|
||||||
|
],
|
||||||
|
shortTitle: "Open Ice Cubes",
|
||||||
|
systemImageName: "cube"
|
||||||
|
)
|
||||||
|
AppShortcut(
|
||||||
|
intent: PostImageIntent(),
|
||||||
|
phrases: [
|
||||||
|
"Post images in \(.applicationName)",
|
||||||
|
"Post an image in \(.applicationName)",
|
||||||
|
"Send photos with \(.applicationName)",
|
||||||
|
"Send a photo with \(.applicationName)",
|
||||||
|
],
|
||||||
|
shortTitle: "Post a status with an image",
|
||||||
|
systemImageName: "photo"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
61
IceCubesAppIntents/InlinePostIntent.swift
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import AppAccount
|
||||||
|
import AppIntents
|
||||||
|
import Env
|
||||||
|
import Foundation
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
|
||||||
|
enum PostVisibility: String, AppEnum {
|
||||||
|
case direct, priv, unlisted, pub
|
||||||
|
|
||||||
|
public static var caseDisplayRepresentations: [PostVisibility: DisplayRepresentation] {
|
||||||
|
[.direct: "Private",
|
||||||
|
.priv: "Followers Only",
|
||||||
|
.unlisted: "Quiet Public",
|
||||||
|
.pub: "Public"]
|
||||||
|
}
|
||||||
|
|
||||||
|
static var typeDisplayName: LocalizedStringResource { "Visibility" }
|
||||||
|
|
||||||
|
public static let typeDisplayRepresentation: TypeDisplayRepresentation = "Visibility"
|
||||||
|
|
||||||
|
var toAppVisibility: Models.Visibility {
|
||||||
|
switch self {
|
||||||
|
case .direct:
|
||||||
|
.direct
|
||||||
|
case .priv:
|
||||||
|
.priv
|
||||||
|
case .unlisted:
|
||||||
|
.unlisted
|
||||||
|
case .pub:
|
||||||
|
.pub
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct InlinePostIntent: AppIntent {
|
||||||
|
static let title: LocalizedStringResource = "Send post to Mastodon"
|
||||||
|
static let description: IntentDescription = "Send a text post to Mastodon with Ice Cubes"
|
||||||
|
static let openAppWhenRun: Bool = false
|
||||||
|
|
||||||
|
@Parameter(title: "Account", requestValueDialog: IntentDialog("Account"))
|
||||||
|
var account: AppAccountEntity
|
||||||
|
|
||||||
|
@Parameter(title: "Post visibility", requestValueDialog: IntentDialog("Visibility of your post"))
|
||||||
|
var visibility: PostVisibility
|
||||||
|
|
||||||
|
@Parameter(title: "Post content", requestValueDialog: IntentDialog("Content of the post to be sent to Mastodon"))
|
||||||
|
var content: String
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView {
|
||||||
|
let client = Client(server: account.account.server, version: .v1, oauthToken: account.account.oauthToken)
|
||||||
|
let status = StatusData(status: content, visibility: visibility.toAppVisibility)
|
||||||
|
do {
|
||||||
|
let status: Status = try await client.post(endpoint: Statuses.postStatus(json: status))
|
||||||
|
return .result(dialog: "\(status.content.asRawText) was posted on Mastodon")
|
||||||
|
} catch {
|
||||||
|
return .result(dialog: "An error occured while posting to Mastodon, please try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
IceCubesAppIntents/ListEntity.swift
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
import AppAccount
|
||||||
|
import AppIntents
|
||||||
|
import Env
|
||||||
|
import Foundation
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import Timeline
|
||||||
|
|
||||||
|
public struct ListEntity: Identifiable, AppEntity {
|
||||||
|
public var id: String { list.id }
|
||||||
|
|
||||||
|
public let list: Models.List
|
||||||
|
|
||||||
|
public static let defaultQuery = DefaultListEntityQuery()
|
||||||
|
|
||||||
|
public static let typeDisplayRepresentation: TypeDisplayRepresentation = "List"
|
||||||
|
|
||||||
|
public var displayRepresentation: DisplayRepresentation {
|
||||||
|
DisplayRepresentation(title: "\(list.title)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DefaultListEntityQuery: EntityQuery {
|
||||||
|
public init() {}
|
||||||
|
|
||||||
|
@IntentParameterDependency<ListsWidgetConfiguration>(
|
||||||
|
\.$account
|
||||||
|
)
|
||||||
|
var account
|
||||||
|
|
||||||
|
public func entities(for _: [ListEntity.ID]) async throws -> [ListEntity] {
|
||||||
|
await fetchLists().map{ .init(list: $0 )}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func suggestedEntities() async throws -> [ListEntity] {
|
||||||
|
await fetchLists().map{ .init(list: $0 )}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func defaultResult() async -> ListEntity? {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fetchLists() async -> [Models.List] {
|
||||||
|
guard let account = account?.account.account else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
let client = Client(server: account.server, oauthToken: account.oauthToken)
|
||||||
|
do {
|
||||||
|
let lists: [Models.List] = try await client.get(endpoint: Lists.lists)
|
||||||
|
return lists
|
||||||
|
} catch {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
IceCubesAppIntents/PostImageIntent.swift
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import AppIntents
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct PostImageIntent: AppIntent {
|
||||||
|
static let title: LocalizedStringResource = "Post an image to Mastodon"
|
||||||
|
static let description: IntentDescription = "Use Ice Cubes to compose a post with an image to Mastodon"
|
||||||
|
static let openAppWhenRun: Bool = true
|
||||||
|
|
||||||
|
@Parameter(title: "Image",
|
||||||
|
description: "Image to post on Mastodon",
|
||||||
|
supportedTypeIdentifiers: ["public.image"],
|
||||||
|
inputConnectionBehavior: .connectToPreviousIntentResult)
|
||||||
|
var images: [IntentFile]?
|
||||||
|
|
||||||
|
func perform() async throws -> some IntentResult {
|
||||||
|
AppIntentService.shared.handledIntent = .init(intent: self)
|
||||||
|
return .result()
|
||||||
|
}
|
||||||
|
}
|
16
IceCubesAppIntents/PostIntent.swift
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import AppIntents
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct PostIntent: AppIntent {
|
||||||
|
static let title: LocalizedStringResource = "Compose a post to Mastodon"
|
||||||
|
static let description: IntentDescription = "Use Ice Cubes to compose a post for Mastodon"
|
||||||
|
static let openAppWhenRun: Bool = true
|
||||||
|
|
||||||
|
@Parameter(title: "Post content", inputConnectionBehavior: .connectToPreviousIntentResult)
|
||||||
|
var content: String?
|
||||||
|
|
||||||
|
func perform() async throws -> some IntentResult {
|
||||||
|
AppIntentService.shared.handledIntent = .init(intent: self)
|
||||||
|
return .result()
|
||||||
|
}
|
||||||
|
}
|
89
IceCubesAppIntents/TabIntent.swift
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
import AppIntents
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum TabEnum: String, AppEnum, Sendable {
|
||||||
|
case timeline, notifications, mentions, explore, messages, settings
|
||||||
|
case trending, federated, local
|
||||||
|
case profile
|
||||||
|
case bookmarks
|
||||||
|
case favorites
|
||||||
|
case post
|
||||||
|
case followedTags
|
||||||
|
case lists
|
||||||
|
case links
|
||||||
|
|
||||||
|
static var typeDisplayName: LocalizedStringResource { "Tab" }
|
||||||
|
|
||||||
|
static let typeDisplayRepresentation: TypeDisplayRepresentation = "Tab"
|
||||||
|
|
||||||
|
nonisolated static var caseDisplayRepresentations: [TabEnum: DisplayRepresentation] {
|
||||||
|
[.timeline: .init(title: "Home Timeline"),
|
||||||
|
.trending: .init(title: "Trending Timeline"),
|
||||||
|
.federated: .init(title: "Federated Timeline"),
|
||||||
|
.local: .init(title: "Local Timeline"),
|
||||||
|
.notifications: .init(title: "Notifications"),
|
||||||
|
.mentions: .init(title: "Mentions"),
|
||||||
|
.explore: .init(title: "Explore & Trending"),
|
||||||
|
.messages: .init(title: "Private Messages"),
|
||||||
|
.settings: .init(title: "Settings"),
|
||||||
|
.profile: .init(title: "Profile"),
|
||||||
|
.bookmarks: .init(title: "Bookmarks"),
|
||||||
|
.favorites: .init(title: "Favorites"),
|
||||||
|
.followedTags: .init(title: "Followed Tags"),
|
||||||
|
.lists: .init(title: "Lists"),
|
||||||
|
.links: .init(title: "Trending Links"),
|
||||||
|
.post: .init(title: "New post")]
|
||||||
|
}
|
||||||
|
|
||||||
|
var toAppTab: Tab {
|
||||||
|
switch self {
|
||||||
|
case .timeline:
|
||||||
|
.timeline
|
||||||
|
case .notifications:
|
||||||
|
.notifications
|
||||||
|
case .mentions:
|
||||||
|
.mentions
|
||||||
|
case .explore:
|
||||||
|
.explore
|
||||||
|
case .messages:
|
||||||
|
.messages
|
||||||
|
case .settings:
|
||||||
|
.settings
|
||||||
|
case .trending:
|
||||||
|
.trending
|
||||||
|
case .federated:
|
||||||
|
.federated
|
||||||
|
case .local:
|
||||||
|
.local
|
||||||
|
case .profile:
|
||||||
|
.profile
|
||||||
|
case .bookmarks:
|
||||||
|
.bookmarks
|
||||||
|
case .favorites:
|
||||||
|
.favorites
|
||||||
|
case .post:
|
||||||
|
.post
|
||||||
|
case .followedTags:
|
||||||
|
.followedTags
|
||||||
|
case .lists:
|
||||||
|
.lists
|
||||||
|
case .links:
|
||||||
|
.links
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TabIntent: AppIntent {
|
||||||
|
static let title: LocalizedStringResource = "Open on a tab"
|
||||||
|
static let description: IntentDescription = "Open the app on a specific tab"
|
||||||
|
static let openAppWhenRun: Bool = true
|
||||||
|
|
||||||
|
@Parameter(title: "Selected tab")
|
||||||
|
var tab: TabEnum
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func perform() async throws -> some IntentResult {
|
||||||
|
AppIntentService.shared.handledIntent = .init(intent: self)
|
||||||
|
return .result()
|
||||||
|
}
|
||||||
|
}
|
37
IceCubesAppIntents/TimelineFilterEntity.swift
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import AppAccount
|
||||||
|
import AppIntents
|
||||||
|
import Env
|
||||||
|
import Foundation
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import Timeline
|
||||||
|
|
||||||
|
public struct TimelineFilterEntity: Identifiable, AppEntity {
|
||||||
|
public var id: String { timeline.id }
|
||||||
|
|
||||||
|
public let timeline: TimelineFilter
|
||||||
|
|
||||||
|
public static let defaultQuery = DefaultTimelineEntityQuery()
|
||||||
|
|
||||||
|
public static let typeDisplayRepresentation: TypeDisplayRepresentation = "TimelineFilter"
|
||||||
|
|
||||||
|
public var displayRepresentation: DisplayRepresentation {
|
||||||
|
DisplayRepresentation(title: "\(timeline.title)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DefaultTimelineEntityQuery: EntityQuery {
|
||||||
|
public init() {}
|
||||||
|
|
||||||
|
public func entities(for _: [TimelineFilter.ID]) async throws -> [TimelineFilterEntity] {
|
||||||
|
[.home, .trending, .federated, .local].map { .init(timeline: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func suggestedEntities() async throws -> [TimelineFilterEntity] {
|
||||||
|
[.home, .trending, .federated, .local].map { .init(timeline: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public func defaultResult() async -> TimelineFilterEntity? {
|
||||||
|
.init(timeline: .home)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct AccountWidgetProvider: AppIntentTimelineProvider {
|
||||||
|
func placeholder(in _: Context) -> AccountWidgetEntry {
|
||||||
|
.init(date: Date(), account: .placeholder(), avatar: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshot(for configuration: AccountWidgetConfiguration, in context: Context) async -> AccountWidgetEntry {
|
||||||
|
let account = await fetchAccount(configuration: configuration)
|
||||||
|
return .init(date: Date(), account: account, avatar: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(for configuration: AccountWidgetConfiguration, in context: Context) async -> Timeline<AccountWidgetEntry> {
|
||||||
|
let account = await fetchAccount(configuration: configuration)
|
||||||
|
let images = try? await loadImages(urls: [account.avatar])
|
||||||
|
return .init(entries: [.init(date: Date(), account: account, avatar: images?.first?.value)],
|
||||||
|
policy: .atEnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fetchAccount(configuration: AccountWidgetConfiguration) async -> Account {
|
||||||
|
let client = Client(server: configuration.account.account.server,
|
||||||
|
oauthToken: configuration.account.account.oauthToken)
|
||||||
|
do {
|
||||||
|
let account: Account = try await client.get(endpoint: Accounts.verifyCredentials)
|
||||||
|
return account
|
||||||
|
} catch {
|
||||||
|
return .placeholder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccountWidgetEntry: TimelineEntry {
|
||||||
|
let date: Date
|
||||||
|
let account: Account
|
||||||
|
let avatar: UIImage?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AccountWidget: Widget {
|
||||||
|
let kind: String = "AccountWidget"
|
||||||
|
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
AppIntentConfiguration(kind: kind,
|
||||||
|
intent: AccountWidgetConfiguration.self,
|
||||||
|
provider: AccountWidgetProvider())
|
||||||
|
{ entry in
|
||||||
|
AccountWidgetView(entry: entry)
|
||||||
|
.containerBackground(Color("WidgetBackground").gradient, for: .widget)
|
||||||
|
}
|
||||||
|
.configurationDisplayName("Account")
|
||||||
|
.description("Show information about your Mastodon account")
|
||||||
|
.supportedFamilies([.systemSmall])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview(as: .systemSmall) {
|
||||||
|
AccountWidget()
|
||||||
|
} timeline: {
|
||||||
|
AccountWidgetEntry(date: Date(), account: .placeholder(), avatar: nil)
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import AppIntents
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct AccountWidgetConfiguration: WidgetConfigurationIntent {
|
||||||
|
static let title: LocalizedStringResource = "Account Widget Configuration"
|
||||||
|
static let description = IntentDescription("Choose the account for this widget")
|
||||||
|
|
||||||
|
@Parameter(title: "Account")
|
||||||
|
var account: AppAccountEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AccountWidgetConfiguration {
|
||||||
|
static var previewAccount: AccountWidgetConfiguration {
|
||||||
|
let intent = AccountWidgetConfiguration()
|
||||||
|
intent.account = .init(account: .init(server: "Test", accountName: "Test account"))
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct AccountWidgetView: View {
|
||||||
|
var entry: AccountWidgetProvider.Entry
|
||||||
|
|
||||||
|
@Environment(\.widgetFamily) var family
|
||||||
|
@Environment(\.redactionReasons) var redacted
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .center, spacing: 4) {
|
||||||
|
if let avatar = entry.avatar {
|
||||||
|
Image(uiImage: avatar)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 64, height: 64)
|
||||||
|
.clipShape(Circle())
|
||||||
|
Text("\(entry.account.followersCount ?? 0)")
|
||||||
|
.font(.title)
|
||||||
|
.fontDesign(.rounded)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
.monospacedDigit()
|
||||||
|
Text("Followers")
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.859",
|
||||||
|
"green" : "0.267",
|
||||||
|
"red" : "0.675"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.949",
|
||||||
|
"green" : "0.945",
|
||||||
|
"red" : "0.941"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.133",
|
||||||
|
"green" : "0.082",
|
||||||
|
"red" : "0.067"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct HashtagPostsWidgetProvider: AppIntentTimelineProvider {
|
||||||
|
func placeholder(in _: Context) -> PostsWidgetEntry {
|
||||||
|
.init(date: Date(),
|
||||||
|
title: "#Mastodon",
|
||||||
|
statuses: [.placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshot(for configuration: HashtagPostsWidgetConfiguration, in context: Context) async -> PostsWidgetEntry {
|
||||||
|
if let entry = await timeline(for: configuration, context: context).entries.first {
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
return .init(date: Date(),
|
||||||
|
title: "#Mastodon",
|
||||||
|
statuses: [],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(for configuration: HashtagPostsWidgetConfiguration, in context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
await timeline(for: configuration, context: context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func timeline(for configuration: HashtagPostsWidgetConfiguration, context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
do {
|
||||||
|
let timeline: TimelineFilter = .hashtag(tag: configuration.hashgtag, accountId: nil)
|
||||||
|
let statuses = await loadStatuses(for: timeline,
|
||||||
|
account: configuration.account,
|
||||||
|
widgetFamily: context.family)
|
||||||
|
let images = try await loadImages(urls: statuses.map { $0.account.avatar })
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: timeline.title,
|
||||||
|
statuses: statuses,
|
||||||
|
images: images)], policy: .atEnd)
|
||||||
|
} catch {
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: "#Mastodon",
|
||||||
|
statuses: [],
|
||||||
|
images: [:])],
|
||||||
|
policy: .atEnd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HashtagPostsWidget: Widget {
|
||||||
|
let kind: String = "HashtagPostsWidget"
|
||||||
|
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
AppIntentConfiguration(kind: kind,
|
||||||
|
intent: HashtagPostsWidgetConfiguration.self,
|
||||||
|
provider: HashtagPostsWidgetProvider())
|
||||||
|
{ entry in
|
||||||
|
PostsWidgetView(entry: entry)
|
||||||
|
.containerBackground(Color("WidgetBackground").gradient, for: .widget)
|
||||||
|
}
|
||||||
|
.configurationDisplayName("Hashtag timeline")
|
||||||
|
.description("Show the latest post for the selected hashtag")
|
||||||
|
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview(as: .systemMedium) {
|
||||||
|
HashtagPostsWidget()
|
||||||
|
} timeline: {
|
||||||
|
PostsWidgetEntry(date: .now,
|
||||||
|
title: "#Mastodon",
|
||||||
|
statuses: [.placeholder(), .placeholder(), .placeholder(), .placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import AppIntents
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct HashtagPostsWidgetConfiguration: WidgetConfigurationIntent {
|
||||||
|
static let title: LocalizedStringResource = "Hashtag Widget Configuration"
|
||||||
|
static let description = IntentDescription("Choose the account and hashtag for this widget")
|
||||||
|
|
||||||
|
@Parameter(title: "Account")
|
||||||
|
var account: AppAccountEntity
|
||||||
|
|
||||||
|
@Parameter(title: "Hashtag")
|
||||||
|
var hashgtag: String
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HashtagPostsWidgetConfiguration {
|
||||||
|
static var previewAccount: HashtagPostsWidgetConfiguration {
|
||||||
|
let intent = HashtagPostsWidgetConfiguration()
|
||||||
|
intent.account = .init(account: .init(server: "Test", accountName: "Test account"))
|
||||||
|
intent.hashgtag = "Mastodon"
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import SwiftUI
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct IceCubesAppWidgetsExtensionBundle: WidgetBundle {
|
||||||
|
var body: some Widget {
|
||||||
|
LatestPostsWidget()
|
||||||
|
HashtagPostsWidget()
|
||||||
|
ListsPostWidget()
|
||||||
|
MentionsWidget()
|
||||||
|
AccountWidget()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>keychain-access-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>$(AppIdentifierPrefix)$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||||
|
</array>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.$(BUNDLE_ID_PREFIX).IceCubesApp</string>
|
||||||
|
</array>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -2,7 +2,10 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>DEEPL_SECRET</key>
|
<key>NSExtension</key>
|
||||||
<string>NICE_TRY_AGAIN</string>
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.widgetkit-extension</string>
|
||||||
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
|
@ -0,0 +1,93 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct LatestPostsWidgetProvider: AppIntentTimelineProvider {
|
||||||
|
func placeholder(in _: Context) -> PostsWidgetEntry {
|
||||||
|
.init(date: Date(),
|
||||||
|
title: "Home",
|
||||||
|
statuses: [.placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshot(for configuration: LatestPostsWidgetConfiguration, in context: Context) async -> PostsWidgetEntry {
|
||||||
|
if let entry = await timeline(for: configuration, context: context).entries.first {
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
return .init(date: Date(),
|
||||||
|
title: configuration.timeline.timeline.title,
|
||||||
|
statuses: [],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(for configuration: LatestPostsWidgetConfiguration, in context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
await timeline(for: configuration, context: context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func timeline(for configuration: LatestPostsWidgetConfiguration, context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
do {
|
||||||
|
let statuses = await loadStatuses(for: configuration.timeline.timeline,
|
||||||
|
account: configuration.account,
|
||||||
|
widgetFamily: context.family)
|
||||||
|
let images = try await loadImages(urls: statuses.map { $0.account.avatar })
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: configuration.timeline.timeline.title,
|
||||||
|
statuses: statuses,
|
||||||
|
images: images)], policy: .atEnd)
|
||||||
|
} catch {
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: configuration.timeline.timeline.title,
|
||||||
|
statuses: [],
|
||||||
|
images: [:])],
|
||||||
|
policy: .atEnd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadImages(urls: [URL]) async throws -> [URL: UIImage] {
|
||||||
|
try await withThrowingTaskGroup(of: (URL, UIImage?).self) { group in
|
||||||
|
for url in urls {
|
||||||
|
group.addTask {
|
||||||
|
let response = try await URLSession.shared.data(from: url)
|
||||||
|
return (url, UIImage(data: response.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var images: [URL: UIImage] = [:]
|
||||||
|
|
||||||
|
for try await (url, image) in group {
|
||||||
|
images[url] = image
|
||||||
|
}
|
||||||
|
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LatestPostsWidget: Widget {
|
||||||
|
let kind: String = "LatestPostsWidget"
|
||||||
|
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
AppIntentConfiguration(kind: kind,
|
||||||
|
intent: LatestPostsWidgetConfiguration.self,
|
||||||
|
provider: LatestPostsWidgetProvider())
|
||||||
|
{ entry in
|
||||||
|
PostsWidgetView(entry: entry)
|
||||||
|
.containerBackground(Color("WidgetBackground").gradient, for: .widget)
|
||||||
|
}
|
||||||
|
.configurationDisplayName("Latest posts")
|
||||||
|
.description("Show the latest post for the selected timeline")
|
||||||
|
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview(as: .systemMedium) {
|
||||||
|
LatestPostsWidget()
|
||||||
|
} timeline: {
|
||||||
|
PostsWidgetEntry(date: .now,
|
||||||
|
title: "Mastodon",
|
||||||
|
statuses: [.placeholder(), .placeholder(), .placeholder(), .placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import AppIntents
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct LatestPostsWidgetConfiguration: WidgetConfigurationIntent {
|
||||||
|
static let title: LocalizedStringResource = "Timeline Widget Configuration"
|
||||||
|
static let description = IntentDescription("Choose the account and timeline for this widget")
|
||||||
|
|
||||||
|
@Parameter(title: "Account")
|
||||||
|
var account: AppAccountEntity
|
||||||
|
|
||||||
|
@Parameter(title: "Timeline")
|
||||||
|
var timeline: TimelineFilterEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
extension LatestPostsWidgetConfiguration {
|
||||||
|
static var previewAccount: LatestPostsWidgetConfiguration {
|
||||||
|
let intent = LatestPostsWidgetConfiguration()
|
||||||
|
intent.account = .init(account: .init(server: "Test", accountName: "Test account"))
|
||||||
|
intent.timeline = .init(timeline: .home)
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
}
|
75
IceCubesAppWidgetsExtension/ListsWidget/ListsWidget.swift
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct ListsWidgetProvider: AppIntentTimelineProvider {
|
||||||
|
func placeholder(in _: Context) -> PostsWidgetEntry {
|
||||||
|
.init(date: Date(),
|
||||||
|
title: "List name",
|
||||||
|
statuses: [.placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshot(for configuration: ListsWidgetConfiguration, in context: Context) async -> PostsWidgetEntry {
|
||||||
|
if let entry = await timeline(for: configuration, context: context).entries.first {
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
return .init(date: Date(),
|
||||||
|
title: "List name",
|
||||||
|
statuses: [],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(for configuration: ListsWidgetConfiguration, in context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
await timeline(for: configuration, context: context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func timeline(for configuration: ListsWidgetConfiguration, context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
do {
|
||||||
|
let timeline: TimelineFilter = .list(list: configuration.timeline.list)
|
||||||
|
let statuses = await loadStatuses(for: timeline,
|
||||||
|
account: configuration.account,
|
||||||
|
widgetFamily: context.family)
|
||||||
|
let images = try await loadImages(urls: statuses.map { $0.account.avatar })
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: timeline.title,
|
||||||
|
statuses: statuses,
|
||||||
|
images: images)], policy: .atEnd)
|
||||||
|
} catch {
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: "List name",
|
||||||
|
statuses: [],
|
||||||
|
images: [:])],
|
||||||
|
policy: .atEnd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ListsPostWidget: Widget {
|
||||||
|
let kind: String = "ListsPostWidget"
|
||||||
|
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
AppIntentConfiguration(kind: kind,
|
||||||
|
intent: ListsWidgetConfiguration.self,
|
||||||
|
provider: ListsWidgetProvider())
|
||||||
|
{ entry in
|
||||||
|
PostsWidgetView(entry: entry)
|
||||||
|
.containerBackground(Color("WidgetBackground").gradient, for: .widget)
|
||||||
|
}
|
||||||
|
.configurationDisplayName("List timeline")
|
||||||
|
.description("Show the latest post for the selected list")
|
||||||
|
.supportedFamilies([.systemSmall, .systemMedium, .systemLarge, .systemExtraLarge])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview(as: .systemMedium) {
|
||||||
|
ListsPostWidget()
|
||||||
|
} timeline: {
|
||||||
|
PostsWidgetEntry(date: .now,
|
||||||
|
title: "List name",
|
||||||
|
statuses: [.placeholder(), .placeholder(), .placeholder(), .placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import AppIntents
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct ListsWidgetConfiguration: WidgetConfigurationIntent {
|
||||||
|
static let title: LocalizedStringResource = "Configuration"
|
||||||
|
static let description = IntentDescription("Choose the account and list for this widget")
|
||||||
|
|
||||||
|
@Parameter(title: "Account")
|
||||||
|
var account: AppAccountEntity
|
||||||
|
|
||||||
|
@Parameter(title: "List")
|
||||||
|
var timeline: ListEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ListsWidgetConfiguration {
|
||||||
|
static var previewAccount: LatestPostsWidgetConfiguration {
|
||||||
|
let intent = LatestPostsWidgetConfiguration()
|
||||||
|
intent.account = .init(account: .init(server: "Test", accountName: "Test account"))
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct MentionsWidgetProvider: AppIntentTimelineProvider {
|
||||||
|
func placeholder(in _: Context) -> PostsWidgetEntry {
|
||||||
|
.init(date: Date(),
|
||||||
|
title: "Mentions",
|
||||||
|
statuses: [.placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshot(for configuration: MentionsWidgetConfiguration, in context: Context) async -> PostsWidgetEntry {
|
||||||
|
if let entry = await timeline(for: configuration, context: context).entries.first {
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
return .init(date: Date(),
|
||||||
|
title: "Mentions",
|
||||||
|
statuses: [],
|
||||||
|
images: [:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeline(for configuration: MentionsWidgetConfiguration, in context: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
await timeline(for: configuration, context: context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func timeline(for configuration: MentionsWidgetConfiguration, context _: Context) async -> Timeline<PostsWidgetEntry> {
|
||||||
|
do {
|
||||||
|
let client = Client(server: configuration.account.account.server,
|
||||||
|
oauthToken: configuration.account.account.oauthToken)
|
||||||
|
var excludedTypes = Models.Notification.NotificationType.allCases
|
||||||
|
excludedTypes.removeAll(where: { $0 == .mention })
|
||||||
|
let notifications: [Models.Notification] =
|
||||||
|
try await client.get(endpoint: Notifications.notifications(minId: nil,
|
||||||
|
maxId: nil,
|
||||||
|
types: excludedTypes.map(\.rawValue),
|
||||||
|
limit: 5))
|
||||||
|
let statuses = notifications.compactMap { $0.status }
|
||||||
|
let images = try await loadImages(urls: statuses.map { $0.account.avatar })
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: "Mentions",
|
||||||
|
statuses: statuses,
|
||||||
|
images: images)], policy: .atEnd)
|
||||||
|
} catch {
|
||||||
|
return Timeline(entries: [.init(date: Date(),
|
||||||
|
title: "Mentions",
|
||||||
|
statuses: [],
|
||||||
|
images: [:])],
|
||||||
|
policy: .atEnd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MentionsWidget: Widget {
|
||||||
|
let kind: String = "MentionsWidget"
|
||||||
|
|
||||||
|
var body: some WidgetConfiguration {
|
||||||
|
AppIntentConfiguration(kind: kind,
|
||||||
|
intent: MentionsWidgetConfiguration.self,
|
||||||
|
provider: MentionsWidgetProvider())
|
||||||
|
{ entry in
|
||||||
|
PostsWidgetView(entry: entry)
|
||||||
|
.containerBackground(Color("WidgetBackground").gradient, for: .widget)
|
||||||
|
}
|
||||||
|
.configurationDisplayName("Mentions")
|
||||||
|
.description("Show the latest mentions for the selected account.")
|
||||||
|
.supportedFamilies([.systemLarge, .systemExtraLarge])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview(as: .systemMedium) {
|
||||||
|
MentionsWidget()
|
||||||
|
} timeline: {
|
||||||
|
PostsWidgetEntry(date: .now,
|
||||||
|
title: "Mentions",
|
||||||
|
statuses: [.placeholder(), .placeholder(), .placeholder(), .placeholder()],
|
||||||
|
images: [:])
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import AppIntents
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct MentionsWidgetConfiguration: WidgetConfigurationIntent {
|
||||||
|
static let title: LocalizedStringResource = "Mentions Widget Configuration"
|
||||||
|
static let description = IntentDescription("Choose the account for this widget")
|
||||||
|
|
||||||
|
@Parameter(title: "Account")
|
||||||
|
var account: AppAccountEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MentionsWidgetConfiguration {
|
||||||
|
static var previewAccount: MentionsWidgetConfiguration {
|
||||||
|
let intent = MentionsWidgetConfiguration()
|
||||||
|
intent.account = .init(account: .init(server: "Test", accountName: "Test account"))
|
||||||
|
return intent
|
||||||
|
}
|
||||||
|
}
|
96
IceCubesAppWidgetsExtension/Shared/PostsWidgetView.swift
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import DesignSystem
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
import SwiftUI
|
||||||
|
import Timeline
|
||||||
|
import WidgetKit
|
||||||
|
|
||||||
|
struct PostsWidgetEntry: TimelineEntry {
|
||||||
|
let date: Date
|
||||||
|
let title: String
|
||||||
|
let statuses: [Status]
|
||||||
|
let images: [URL: UIImage]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PostsWidgetView: View {
|
||||||
|
var entry: LatestPostsWidgetProvider.Entry
|
||||||
|
|
||||||
|
@Environment(\.widgetFamily) var family
|
||||||
|
@Environment(\.redactionReasons) var redacted
|
||||||
|
|
||||||
|
var contentLineLimit: Int {
|
||||||
|
switch family {
|
||||||
|
case .systemSmall, .systemMedium:
|
||||||
|
return 5
|
||||||
|
default:
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
headerView
|
||||||
|
ForEach(entry.statuses) { status in
|
||||||
|
makeStatusView(status)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var headerView: some View {
|
||||||
|
HStack {
|
||||||
|
Text(entry.title)
|
||||||
|
Spacer()
|
||||||
|
Image(systemName: "cube")
|
||||||
|
}
|
||||||
|
.font(.subheadline)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
.foregroundStyle(Color("AccentColor"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func makeStatusView(_ status: Status) -> some View {
|
||||||
|
if let url = URL(string: status.url ?? "") {
|
||||||
|
Link(destination: url, label: {
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
|
makeStatusHeaderView(status)
|
||||||
|
Text(status.content.asSafeMarkdownAttributedString)
|
||||||
|
.font(.footnote)
|
||||||
|
.lineLimit(contentLineLimit)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.padding(.leading, 20)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeStatusHeaderView(_ status: Status) -> some View {
|
||||||
|
HStack(alignment: .center, spacing: 4) {
|
||||||
|
if let image = entry.images[status.account.avatar] {
|
||||||
|
Image(uiImage: image)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 16, height: 16)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else {
|
||||||
|
Circle()
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
.frame(width: 16, height: 16)
|
||||||
|
}
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
Text(status.account.safeDisplayName)
|
||||||
|
.foregroundStyle(.primary)
|
||||||
|
if family != .systemSmall {
|
||||||
|
Text(" @")
|
||||||
|
.foregroundStyle(.tertiary)
|
||||||
|
Text(status.account.username)
|
||||||
|
.foregroundStyle(.tertiary)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.font(.footnote)
|
||||||
|
.fontWeight(.semibold)
|
||||||
|
.lineLimit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|