Compare commits

...

142 Commits

Author SHA1 Message Date
Marcin Czachurski 910f68f750 Remove QRCode dependencies 2023-12-27 10:08:36 +01:00
Marcin Czachurski 16bd7e69c1 Add new empty result view 2023-12-27 08:12:54 +01:00
Marcin Czachurski cb34bf96a2
Merge pull request #105 from xabirequejo/develop
Plural variants for Basque
2023-12-10 12:05:14 +01:00
Marcin Czachurski 79d0bdea47
Merge pull request #104 from PattaFeuFeu/patch-1
Rephrase odd German translations
2023-12-10 12:04:26 +01:00
Xabi b62f7d8c37
Update EU localisation
Added plural variants and other improvements for Basque
2023-12-07 17:41:29 +01:00
Patrick Geselbracht c5975eb81a
Replace Zeitleiste with Timeline 2023-12-07 17:35:28 +01:00
Patrick Geselbracht 2d6a614264
Replace Zuhause with Deine Timeline 2023-12-07 15:50:35 +01:00
Patrick Geselbracht 452692d82a
Update Localizable.xcstrings 2023-12-07 15:49:43 +01:00
Patrick Geselbracht 771333f5ca
Improve wording for enableReboostOnTimeline 2023-12-07 15:49:19 +01:00
Patrick Geselbracht dde452033b
Replace weird boost translation 2023-12-07 13:30:50 +01:00
Xabi 341cb55e59 plural variations 2023-12-07 00:02:04 +01:00
Patrick Geselbracht f8d2e61ca3
Rephrase odd “Joined” string in profile 2023-12-06 09:41:35 +01:00
Marcin Czachurski 1d1fd1a631 Fix translation and update Nuke 2023-12-05 17:08:17 +01:00
Marcin Czachurski f1a47a5c6d
Merge pull request #102 from xabirequejo/develop
Basque localisation
2023-12-05 16:59:10 +01:00
Xabi 669746b2ba
Basque localisation
Updated a few strings marked for reviewing.
2023-12-04 19:14:31 +01:00
Marcin Czachurski b63d97053a Change version to 2.0.4 2023-12-01 23:06:34 +01:00
Marcin Czachurski a2e17b1a48 Move german translation to xcstrings files 2023-12-01 23:03:29 +01:00
Marcin Czachurski c895c1ac58
Merge pull request #99 from tobybaier/toby/de_DE
german translation
2023-12-01 21:37:49 +01:00
Toby Baier a2233ff3af
Update Localizable.strings
needs to be the same as the other occurance
2023-12-01 15:09:16 +01:00
Toby Baier eca913ed5a
less awkward 2023-12-01 14:55:32 +01:00
Toby Baier dcd717a356
Update Localizable.strings
decided to go for "Follower" also in German, since everyone knows the word. In all other contexts, it's "folgen" and passive ("werden gefolgt" instead of "Du folgst" or "ich folge")
2023-12-01 14:41:29 +01:00
Toby Baier c67182d4e9
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:37:16 +01:00
Toby Baier 468554d889
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:30:31 +01:00
Toby Baier 14b66a02cf
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:30:08 +01:00
Toby Baier 469c5e94c4
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:29:45 +01:00
Toby Baier d74193c9b3
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:29:18 +01:00
Toby Baier 51d6869ad0
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:28:37 +01:00
Toby Baier 6cd6ff10ed
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:28:10 +01:00
Toby Baier 152583f42c
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:27:39 +01:00
Toby Baier a1e11ecaac
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:27:18 +01:00
Toby Baier 32d75d3b39
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:26:57 +01:00
Toby Baier cf0f76ef31
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:26:32 +01:00
Toby Baier b18870c92f
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:26:10 +01:00
Toby Baier 45f8f385f7
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:25:47 +01:00
Toby Baier cc97bcff00
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:25:14 +01:00
Toby Baier 24ec245615
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:24:58 +01:00
Toby Baier fe770fcbfe
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:24:43 +01:00
Toby Baier b8b0234b9c
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:24:27 +01:00
Toby Baier d3188b931f
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:24:07 +01:00
Toby Baier 36d85b7ef1
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:23:51 +01:00
Toby Baier 171e4a8d38
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:23:30 +01:00
Toby Baier 6f97190d5e
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:22:50 +01:00
Toby Baier 923b8c3e9f
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:22:32 +01:00
Toby Baier 4637591b79
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:22:16 +01:00
Toby Baier 99f356cb7f
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:21:58 +01:00
Toby Baier 2e131fcf65
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:21:40 +01:00
Toby Baier a84bfc2328
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:21:14 +01:00
Toby Baier f6a94134da
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:20:54 +01:00
Toby Baier 66044c0fe6
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:20:02 +01:00
Toby Baier 125020b152
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:19:49 +01:00
Toby Baier 22585c873c
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:19:41 +01:00
Toby Baier 2bd6376187
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:19:33 +01:00
Toby Baier 1f03f0641a
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:19:12 +01:00
Toby Baier 13da5e52e5
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:18:48 +01:00
Toby Baier f429602b23
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:18:31 +01:00
Toby Baier 4e695887e4
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:18:23 +01:00
Toby Baier f5d425db02
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:18:15 +01:00
Toby Baier b27115f927
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:18:06 +01:00
Toby Baier a3402120cf
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:17:56 +01:00
Toby Baier c18263c9c7
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:17:44 +01:00
Toby Baier bb79f78b64
Improvements from PattaFeuFeu
Co-authored-by: Patrick Geselbracht <github@pattafeufeu.de>
2023-11-30 08:17:13 +01:00
Toby Baier 6d233299a5 remaining translations 2023-11-22 11:05:54 +01:00
Marcin Czachurski 4279533371 Fix not displayed rebloged statuses on timeline 2023-11-21 12:50:40 +01:00
Marcin Czachurski facc2caf5f Improve counter on home timeline 2023-11-20 15:23:42 +01:00
Marcin Czachurski 2a44115bd8 Fix issue with translations and maximum statuses on lists 2023-11-13 13:48:37 +01:00
Marcin Czachurski 2b88870995 Fix crash on 17.1 2023-10-26 07:28:07 +02:00
Marcin Czachurski e16ebcc2e5 Minimalize amount of tips 2023-10-25 17:03:46 +02:00
Marcin Czachurski 932202d58b Fix localizations 2023-10-25 16:23:15 +02:00
Marcin Czachurski 1e67357823 Fix labels on photo editor 2023-10-25 09:46:10 +02:00
Marcin Czachurski af0bb99ce3 Remove app state from background tasks 2023-10-25 08:36:04 +02:00
Marcin Czachurski 9be8a36b1c Change notification icon and add more logs 2023-10-25 08:05:50 +02:00
Marcin Czachurski 1292000620 Fix notification counter 2023-10-24 19:38:47 +02:00
Marcin Czachurski 3b29f792b6 Fix refreshing counter when it's disabled 2023-10-24 16:35:03 +02:00
Marcin Czachurski 6ced647807 Fix refreshing counter when it's disabled 2023-10-24 16:09:00 +02:00
Marcin Czachurski bd56408ce8 Fix amount of new notifications indicator 2023-10-24 16:02:02 +02:00
Marcin Czachurski 8de6c937ec Add notification indicator 2023-10-24 15:44:46 +02:00
Marcin Czachurski db407195f2 Add application badge with number of new notifications 2023-10-24 14:04:23 +02:00
Marcin Czachurski 1af66b189d Fix visible duplicated status in same portion of data: 2023-10-23 09:26:52 +02:00
Marcin Czachurski 8309cdecbd Show disabled boosts accounts 2023-10-23 08:47:36 +02:00
Marcin Czachurski eed0f72d53 Change icon for trending accounts 2023-10-23 08:01:02 +02:00
Marcin Czachurski 5aed65cb4d Add trending to custom menu items 2023-10-23 07:56:32 +02:00
Marcin Czachurski 9703d26656 Change size of images and add prefetch 2023-10-22 18:51:55 +02:00
Marcin Czachurski fc4d6f7f42 Revert back loader color 2023-10-22 15:59:33 +02:00
Marcin Czachurski bfde175aab Refresh application statuses after account switch 2023-10-22 14:20:32 +02:00
Marcin Czachurski 1199b67765
Merge pull request #95 from VernissageApp/bugfix/fix-refreshing-comments
#19 Fix refreshing comments after publishing new one
2023-10-22 14:03:37 +02:00
Marcin Czachurski ab78314f95 #19 Fix refreshing comments after publishing new one 2023-10-22 14:01:36 +02:00
Marcin Czachurski 67d393c272
Merge pull request #94 from VernissageApp/bugfix/publish-without-text
Publish without text
2023-10-22 13:30:17 +02:00
Marcin Czachurski 1eca78fd8c Fix deleting status 2023-10-22 13:26:55 +02:00
Marcin Czachurski 9d90622ff2 #73 Publish status without text message 2023-10-22 13:19:01 +02:00
Marcin Czachurski a510d0d0c2 Remove custom indicators 2023-10-22 12:33:43 +02:00
Marcin Czachurski a05e9bee48 Invalidate tips when user did an action 2023-10-22 11:43:57 +02:00
Marcin Czachurski fb93f547ab Remove macos support 2023-10-22 10:15:40 +02:00
Marcin Czachurski 02c62b86d9 Add indicator to notifications icon 2023-10-22 10:09:02 +02:00
Marcin Czachurski 06af34d4c8 Improve widget fetcher 2023-10-21 13:46:05 +02:00
Marcin Czachurski 87951bc674 Add first tips 2023-10-21 09:44:40 +02:00
Marcin Czachurski f3598a9940 Add cache with last loaded statuses on home timeline 2023-10-21 08:18:36 +02:00
Marcin Czachurski 6c3bf3a0fc Fix information about amount of statuses 2023-10-20 18:50:25 +02:00
Marcin Czachurski 28df8b940e Fix issue with loading data whuc has not been visible yet 2023-10-20 18:24:16 +02:00
Marcin Czachurski fffb477cb5
Merge pull request #93 from VernissageApp/feature/swift-core
Feature/swift core
2023-10-20 17:50:53 +02:00
Marcin Czachurski f063338ce4 Change home timeline 2023-10-20 17:35:11 +02:00
Marcin Czachurski bb15356e88 Migrate to SwiftData 2023-10-20 07:45:18 +02:00
Marcin Czachurski a8acc93c3e Move to observables 2023-10-19 13:24:02 +02:00
Marcin Czachurski 27cba57c38 Fix ios17 warnings 2023-10-19 09:29:49 +02:00
Marcin Czachurski df3ae90c94
Merge pull request #92 from VernissageApp/feature/new-translation-system
Feature/new translation system
2023-10-18 17:59:11 +02:00
Marcin Czachurski 5068a19a7d Add Spanish translation 2023-10-18 17:52:49 +02:00
Marcin Czachurski 41f88e90f1 Move translations to xcstring files 2023-10-18 11:14:56 +02:00
Toby Baier c884756614 more strings localized 2023-10-13 12:02:03 +02:00
Marcin Czachurski 7e9fd97efd Fix refreshing counter after switching the account 2023-10-12 12:31:48 +02:00
Marcin Czachurski 5cc7167336 Reduce number of request on home timeline and during application start 2023-10-12 12:06:04 +02:00
Marcin Czachurski d7ad482e35
Merge pull request #88 from xabirequejo/develop
Update EU Localizable.strings
2023-10-11 18:57:33 +02:00
Marcin Czachurski 598d9f77ea
Merge pull request #89 from VernissageApp/feature/improve-widget-image-fetcher
Improve widget image fetcher
2023-10-11 18:57:24 +02:00
Marcin Czachurski 967d046607 Improve widget image fetcher 2023-10-11 18:42:56 +02:00
Marcin Czachurski 5b2c47f4a3 Add imformation about encryption to Info.plist 2023-10-10 19:03:17 +02:00
Marcin Czachurski f2f8b9cd1a Remove Resources folder from xcode project 2023-10-10 18:47:43 +02:00
Marcin Czachurski 58a76541bd Update Drops dependency to newest version 2023-10-10 18:20:38 +02:00
Xabi f5e715b945
Update EU Localizable.strings
Translated: Boosts muted and hide status without ALT text, plus a few minor fixes and missing strings.

I have translated *enable/disable boosts* as *show/hide boosts*, at least for now. I think that enable/disable boosts could fit better as a setting when composing a new status, the same way enable or disable replies/comments works.
2023-10-10 14:48:26 +02:00
Marcin Czachurski 7d228262ba
Merge pull request #87 from VernissageApp/feature/hide-without-alt-text
Hide statuses without alt text
2023-10-10 13:31:26 +02:00
Marcin Czachurski 6a8bc9ef64 Hide statuses without alt text 2023-10-10 13:30:53 +02:00
Marcin Czachurski 51b05ae128
Merge pull request #86 from VernissageApp/feature/hide-account-boosts
Hide account boosts
2023-10-10 10:12:30 +02:00
Marcin Czachurski 4d9ac983ad Hide account boosts 2023-10-10 10:10:24 +02:00
Marcin Czachurski 8721c9b1ca
Merge pull request #84 from xabirequejo/develop
Update EU Localizable.strings
2023-10-09 16:49:53 +02:00
Marcin Czachurski c0a4fd930c
Merge pull request #85 from VernissageApp/feature/trending-people
Change trending people
2023-10-09 16:49:38 +02:00
Marcin Czachurski fc3b4d1296 Change trending people 2023-10-09 16:47:20 +02:00
Xabi 3652e05758
Update EU Localizable.strings
Yeah, I completely missed translating the new strings 😔
2023-10-09 00:33:52 +02:00
Marcin Czachurski c5bcbfeb42
Merge pull request #81 from xabirequejo/develop
Update EU Localizable.strings
2023-10-08 11:45:41 +02:00
Marcin Czachurski 50ac6b5dde
Merge pull request #82 from VernissageApp/feature/reblogs
Feature/reblogs
2023-10-08 11:37:47 +02:00
Marcin Czachurski e601a564d9 Fix reblogs in iPad version 2023-10-08 11:35:45 +02:00
Xabi 421429c5e7
Update EU Localizable.strings
Small improvements
2023-10-06 20:05:51 +02:00
Marcin Czachurski 34c80c1f19 Add new icons 2023-10-06 17:19:53 +02:00
Marcin Czachurski 8b5632aa1c Remove duplicated reblogs 2023-10-04 18:14:12 +02:00
Marcin Czachurski 866496407e Remove tap event from counter 2023-10-03 12:20:11 +02:00
Toby Baier 8cc002a8c8 first few words 2023-10-02 19:53:38 +02:00
Marcin Czachurski 509b54a736 Improve refreshing home timeline 2023-10-01 18:45:49 +02:00
Marcin Czachurski f8241c1488 Fix boost/favourite/bookmark actions for boosted statuses 2023-09-30 13:52:46 +02:00
Marcin Czachurski 89702c6e42 Change image avatars 2023-09-29 16:58:45 +02:00
Marcin Czachurski d8aa3db3ee Add first implementation of reblogs on timeline 2023-09-29 16:03:42 +02:00
Marcin Czachurski 15bf208496 Fix image size and color of active buttons 2023-09-27 16:27:01 +02:00
Marcin Czachurski a83ae0ee24 Merge branch 'develop' of github.com:VernissageApp/Vernissage into develop 2023-09-27 15:43:11 +02:00
Marcin Czachurski b43e203721 Fix width of statuses waterfall view 2023-09-27 15:43:00 +02:00
Marcin Czachurski 11016cffdb
Merge pull request #79 from xabirequejo/develop 2023-09-27 10:24:38 +02:00
Xabi 363ce94657
Update EU Localizable.strings
Just one string for now:
- tags.navigationBar.followedTitle
2023-09-26 21:52:10 +02:00
Marcin Czachurski 221e128303 Add follow/unfollow tags 2023-09-26 20:01:58 +02:00
223 changed files with 19828 additions and 4781 deletions

BIN
Assets/BlueLens.afdesign Normal file

Binary file not shown.

BIN
Assets/BrownLens.afdesign Normal file

Binary file not shown.

Binary file not shown.

BIN
Assets/OrangeLens.afdesign Normal file

Binary file not shown.

BIN
Assets/PinkLens.afdesign Normal file

Binary file not shown.

View File

@ -1,14 +1,13 @@
// swift-tools-version: 5.8
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "ClientKit",
defaultLocalization: "en",
platforms: [
.iOS(.v16),
.macOS(.v12),
.watchOS(.v8)
.iOS(.v17)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.

View File

@ -20,5 +20,13 @@ extension Client {
public func unfollow(tag: String) async throws -> Tag? {
return try await pixelfedClient.unfollow(hashtag: tag)
}
public func followed(maxId: MaxId? = nil,
sinceId: SinceId? = nil,
minId: MinId? = nil,
limit: Int? = nil
) async throws -> Linkable<[Tag]> {
return try await pixelfedClient.followedTags(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
}
}
}

View File

@ -12,8 +12,9 @@ extension Client {
public func getHomeTimeline(maxId: String? = nil,
sinceId: String? = nil,
minId: String? = nil,
limit: Int = 40) async throws -> [Status] {
return try await pixelfedClient.getHomeTimeline(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit)
limit: Int = 40,
includeReblogs: Bool? = nil) async throws -> Linkable<[Status]> {
return try await pixelfedClient.getHomeTimeline(maxId: maxId, sinceId: sinceId, minId: minId, limit: limit, includeReblogs: includeReblogs)
}
public func getStatuses(local: Bool? = nil,
@ -21,7 +22,7 @@ extension Client {
maxId: String? = nil,
sinceId: String? = nil,
minId: String? = nil,
limit: Int = 40) async throws -> [Status] {
limit: Int = 40) async throws -> Linkable<[Status]> {
return try await pixelfedClient.getPublicTimeline(local: local,
remote: remote,
onlyMedia: true,
@ -37,7 +38,7 @@ extension Client {
maxId: String? = nil,
sinceId: String? = nil,
minId: String? = nil,
limit: Int = 40) async throws -> [Status] {
limit: Int = 40) async throws -> Linkable<[Status]> {
return try await pixelfedClient.getTagTimeline(tag: tag,
local: local,
remote: remote,

View File

@ -7,7 +7,7 @@
import Foundation
import PixelfedKit
public class Client: ObservableObject {
@Observable public class Client {
public static let shared = Client()
private init() { }

View File

@ -19,6 +19,11 @@ public extension Status {
func statusContainsImage() -> Bool {
return getAllImageMediaAttachments().isEmpty == false
}
func statusContainsAltText() -> Bool {
let mediaAttachments = self.getAllImageMediaAttachments()
return mediaAttachments.contains(where: { $0.description?.isEmpty == false })
}
func getAllImageMediaAttachments() -> [MediaAttachment] {
if let reblog = self.reblog {

View File

@ -0,0 +1,5 @@
{
"sourceLanguage" : "en",
"strings" : {},
"version" : "1.0"
}

View File

@ -6,7 +6,7 @@
import Foundation
public class AccountModel: ObservableObject, Identifiable {
@Observable public class AccountModel: Identifiable {
public let id: String
public let accessToken: String?
public let refreshToken: String?
@ -27,8 +27,9 @@ public class AccountModel: ObservableObject, Identifiable {
public let url: URL?
public let username: String
public let lastSeenStatusId: String?
@Published public var avatarData: Data?
public let lastSeenNotificationId: String?
public var avatarData: Data?
public init(id: String,
accessToken: String?,
@ -50,6 +51,7 @@ public class AccountModel: ObservableObject, Identifiable {
url: URL?,
username: String,
lastSeenStatusId: String?,
lastSeenNotificationId: String?,
avatarData: Data? = nil) {
self.id = id
self.accessToken = accessToken
@ -72,6 +74,7 @@ public class AccountModel: ObservableObject, Identifiable {
self.username = username
self.lastSeenStatusId = lastSeenStatusId
self.avatarData = avatarData
self.lastSeenNotificationId = lastSeenNotificationId
}
}

View File

@ -7,7 +7,7 @@
import Foundation
import PixelfedKit
public class AttachmentModel: ObservableObject, Identifiable {
@Observable public class AttachmentModel: Identifiable {
public let id: String
public let type: MediaAttachment.MediaAttachmentType
public let url: URL
@ -21,11 +21,11 @@ public class AttachmentModel: ObservableObject, Identifiable {
public let metaImageWidth: Int32?
public let metaImageHeight: Int32?
@Published public var exifCamera: String?
@Published public var exifCreatedDate: String?
@Published public var exifExposure: String?
@Published public var exifLens: String?
@Published public var data: Data?
public var exifCamera: String?
public var exifCreatedDate: String?
public var exifExposure: String?
public var exifLens: String?
public var data: Data?
public init(id: String,
type: MediaAttachment.MediaAttachmentType,

View File

@ -7,8 +7,9 @@
import Foundation
import PixelfedKit
public class StatusModel: ObservableObject {
@Observable public class StatusModel {
public let id: EntityId
public let rebloggedStatusId: EntityId?
public let content: Html
public let uri: String?
@ -37,15 +38,16 @@ public class StatusModel: ObservableObject {
public let reblogStatus: Status?
@Published public var favourited: Bool
@Published public var mediaAttachments: [AttachmentModel]
public var favourited: Bool
public var mediaAttachments: [AttachmentModel]
public init(status: Status) {
self.id = status.id
self.rebloggedStatusId = status.reblog?.id
// If status has been rebloged we are saving orginal status here.
let orginalStatus = status.reblog ?? status
self.id = orginalStatus.id
self.content = orginalStatus.content
self.uri = orginalStatus.uri
self.url = orginalStatus.url
@ -86,6 +88,13 @@ public class StatusModel: ObservableObject {
}
}
public extension StatusModel {
/// Function returns status Id for real status (status with images), even for reboosted statuses.
func getOrginalStatusId() -> EntityId {
return self.rebloggedStatusId ?? self.id
}
}
public extension StatusModel {
func getImageWidth() -> Int32? {
let highestImage = self.mediaAttachments.getHighestImage()

View File

@ -1,35 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import ClientKit
extension AccountData {
func toAccountModel() -> AccountModel {
let accountModel = AccountModel(id: self.id,
accessToken: self.accessToken,
refreshToken: self.refreshToken,
acct: self.acct,
avatar: self.avatar,
clientId: self.clientId,
clientSecret: self.clientSecret,
clientVapidKey: self.clientVapidKey,
createdAt: self.createdAt,
displayName: self.displayName,
followersCount: self.followersCount,
followingCount: self.followingCount,
header: self.header,
locked: self.locked,
note: self.note,
serverUrl: self.serverUrl,
statusesCount: self.statusesCount,
url: self.url,
username: self.username,
lastSeenStatusId: self.lastSeenStatusId,
avatarData: self.avatarData)
return accountModel
}
}

View File

@ -1,12 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
@objc(AccountData)
public class AccountData: NSManagedObject {
}

View File

@ -1,57 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
extension AccountData {
@nonobjc public class func fetchRequest() -> NSFetchRequest<AccountData> {
return NSFetchRequest<AccountData>(entityName: "AccountData")
}
@NSManaged public var accessToken: String?
@NSManaged public var refreshToken: String?
@NSManaged public var acct: String
@NSManaged public var avatar: URL?
@NSManaged public var avatarData: Data?
@NSManaged public var clientId: String
@NSManaged public var clientSecret: String
@NSManaged public var clientVapidKey: String
@NSManaged public var createdAt: String
@NSManaged public var displayName: String?
@NSManaged public var followersCount: Int32
@NSManaged public var followingCount: Int32
@NSManaged public var header: URL?
@NSManaged public var id: String
@NSManaged public var locked: Bool
@NSManaged public var note: String?
@NSManaged public var serverUrl: URL
@NSManaged public var statusesCount: Int32
@NSManaged public var url: URL?
@NSManaged public var username: String
@NSManaged public var statuses: Set<StatusData>?
@NSManaged public var lastSeenStatusId: String?
}
// MARK: Generated accessors for statuses
extension AccountData {
@objc(addStatusesObject:)
@NSManaged public func addToStatuses(_ value: StatusData)
@objc(removeStatusesObject:)
@NSManaged public func removeFromStatuses(_ value: StatusData)
@objc(addStatuses:)
@NSManaged public func addToStatuses(_ values: NSSet)
@objc(removeStatuses:)
@NSManaged public func removeFromStatuses(_ values: NSSet)
}
extension AccountData: Identifiable {
}

166
CoreData/AccountData.swift Normal file
View File

@ -0,0 +1,166 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import SwiftData
import ClientKit
@Model final public class AccountData {
@Attribute(.unique) public var id: String
/// Access token to the server API.
public var accessToken: String?
/// Refresh token which can be used to download new access token.
public var refreshToken: String?
/// Full user name (user name with server address).
public var acct: String
/// URL to user avatar.
public var avatar: URL?
/// Avatar downloaded from server (visible mainly in top navigation bar).
@Attribute(.externalStorage) public var avatarData: Data?
/// Id of OAuth client.
public var clientId: String
/// Secret of OAutch client.
public var clientSecret: String
/// Vapid key of OAuth client.
public var clientVapidKey: String
/// Date of creating user.
public var createdAt: String
/// Human readable user name.
public var displayName: String?
/// Number of followers.
public var followersCount: Int32
/// Number of following users.
public var followingCount: Int32
/// URL to header image visible on user profile.
public var header: URL?
/// User profile is locked.
public var locked: Bool
/// Description on user profile.
public var note: String?
/// Address to server.
public var serverUrl: URL
/// NUmber of statuses added by the user.
public var statusesCount: Int32
/// Url to user profile.
public var url: URL?
/// User name (without server address).
public var username: String
/// Last status seen on home timeline by the user.
public var lastSeenStatusId: String?
/// Last status loaded on home timeline.
public var lastLoadedStatusId: String?
/// JSON string with last objects loaded into home timeline.
public var timelineCache: String?
/// Last notification seen by the user.
public var lastSeenNotificationId: String?
@Relationship(deleteRule: .cascade, inverse: \ViewedStatus.pixelfedAccount) public var viewedStatuses: [ViewedStatus]
@Relationship(deleteRule: .cascade, inverse: \AccountRelationship.pixelfedAccount) public var accountRelationships: [AccountRelationship]
init(
accessToken: String? = nil,
refreshToken: String? = nil,
acct: String = "",
avatar: URL? = nil,
avatarData: Data? = nil,
clientId: String = "",
clientSecret: String = "",
clientVapidKey: String = "",
createdAt: String = "",
displayName: String? = nil,
followersCount: Int32 = .zero,
followingCount: Int32 = .zero,
header: URL? = nil,
id: String = "",
locked: Bool = false,
note: String? = nil,
serverUrl: URL,
statusesCount: Int32 = .zero,
url: URL? = nil,
username: String = "",
viewedStatuses: [ViewedStatus] = [],
accountRelationships: [AccountRelationship] = [],
lastSeenStatusId: String? = nil
) {
self.accessToken = accessToken
self.refreshToken = refreshToken
self.acct = acct
self.avatar = avatar
self.avatarData = avatarData
self.clientId = clientId
self.clientSecret = clientSecret
self.clientVapidKey = clientVapidKey
self.createdAt = createdAt
self.displayName = displayName
self.followersCount = followersCount
self.followingCount = followingCount
self.header = header
self.id = id
self.locked = locked
self.note = note
self.serverUrl = serverUrl
self.statusesCount = statusesCount
self.url = url
self.username = username
self.viewedStatuses = viewedStatuses
self.accountRelationships = accountRelationships
self.lastSeenStatusId = lastSeenStatusId
}
}
extension AccountData: Identifiable {
}
extension AccountData {
func toAccountModel() -> AccountModel {
let accountModel = AccountModel(id: self.id,
accessToken: self.accessToken,
refreshToken: self.refreshToken,
acct: self.acct,
avatar: self.avatar,
clientId: self.clientId,
clientSecret: self.clientSecret,
clientVapidKey: self.clientVapidKey,
createdAt: self.createdAt,
displayName: self.displayName,
followersCount: self.followersCount,
followingCount: self.followingCount,
header: self.header,
locked: self.locked,
note: self.note,
serverUrl: self.serverUrl,
statusesCount: self.statusesCount,
url: self.url,
username: self.username,
lastSeenStatusId: self.lastSeenStatusId,
lastSeenNotificationId: self.lastSeenNotificationId,
avatarData: self.avatarData)
return accountModel
}
}

View File

@ -5,26 +5,29 @@
//
import Foundation
import CoreData
import SwiftData
import PixelfedKit
import EnvironmentKit
class AccountDataHandler {
public static let shared = AccountDataHandler()
private init() { }
func getAccountsData(viewContext: NSManagedObjectContext? = nil) -> [AccountData] {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = AccountData.fetchRequest()
func getAccountsData(modelContext: ModelContext) -> [AccountData] {
do {
return try context.fetch(fetchRequest)
var fetchDescriptor = FetchDescriptor<AccountData>()
fetchDescriptor.includePendingChanges = true
return try modelContext.fetch(fetchDescriptor)
} catch {
CoreDataError.shared.handle(error, message: "Accounts cannot be retrieved (getAccountsData).")
return []
}
}
func getCurrentAccountData(viewContext: NSManagedObjectContext? = nil) -> AccountData? {
let accounts = self.getAccountsData(viewContext: viewContext)
let defaultSettings = ApplicationSettingsHandler.shared.get()
func getCurrentAccountData(modelContext: ModelContext) -> AccountData? {
let accounts = self.getAccountsData(modelContext: modelContext)
let defaultSettings = ApplicationSettingsHandler.shared.get(modelContext: modelContext)
let currentAccount = accounts.first { accountData in
accountData.id == defaultSettings.currentAccount
@ -37,34 +40,69 @@ class AccountDataHandler {
return accounts.first
}
func getAccountData(accountId: String, viewContext: NSManagedObjectContext? = nil) -> AccountData? {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = AccountData.fetchRequest()
fetchRequest.fetchLimit = 1
fetchRequest.predicate = NSPredicate(format: "id = %@", accountId)
func getAccountData(accountId: String, modelContext: ModelContext) -> AccountData? {
do {
return try context.fetch(fetchRequest).first
var fetchDescriptor = FetchDescriptor<AccountData>(
predicate: #Predicate { $0.id == accountId}
)
fetchDescriptor.fetchLimit = 1
fetchDescriptor.includePendingChanges = true
return try modelContext.fetch(fetchDescriptor).first
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching status (getAccountData).")
return nil
}
}
func remove(accountData: AccountData) {
let context = CoreDataHandler.shared.container.viewContext
context.delete(accountData)
func remove(accountData: AccountData, modelContext: ModelContext) {
do {
try context.save()
modelContext.delete(accountData)
try modelContext.save()
} catch {
CoreDataError.shared.handle(error, message: "Error during deleting account data (remove).")
}
}
func update(lastSeenStatusId: String?, lastLoadedStatusId: String?, statuses: Linkable<[Status]>? = nil, applicationState: ApplicationState, modelContext: ModelContext) throws {
guard let accountId = applicationState.account?.id else {
return
}
guard let accountDataFromDb = self.getAccountData(accountId: accountId, modelContext: modelContext) else {
return
}
if (accountDataFromDb.lastSeenStatusId ?? "0") < (lastSeenStatusId ?? "0") {
accountDataFromDb.lastSeenStatusId = lastSeenStatusId
applicationState.lastSeenStatusId = lastSeenStatusId
}
func createAccountDataEntity(viewContext: NSManagedObjectContext? = nil) -> AccountData {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
return AccountData(context: context)
if (accountDataFromDb.lastLoadedStatusId ?? "0") < (lastLoadedStatusId ?? "0") {
accountDataFromDb.lastLoadedStatusId = lastLoadedStatusId
}
if let statuses, let statusesJsonData = try? JSONEncoder().encode(statuses) {
accountDataFromDb.timelineCache = String(data: statusesJsonData, encoding: .utf8)
}
try modelContext.save()
}
func update(lastSeenNotificationId: String?, applicationState: ApplicationState, modelContext: ModelContext) throws {
guard let accountId = applicationState.account?.id else {
return
}
guard let accountDataFromDb = self.getAccountData(accountId: accountId, modelContext: modelContext) else {
return
}
if (accountDataFromDb.lastSeenNotificationId ?? "0") < (lastSeenNotificationId ?? "0") {
accountDataFromDb.lastSeenNotificationId = lastSeenNotificationId
applicationState.lastSeenNotificationId = lastSeenNotificationId
}
try modelContext.save()
}
}

View File

@ -0,0 +1,23 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import SwiftData
@Model final public class AccountRelationship {
@Attribute(.unique) public var accountId: String
public var boostedStatusesMuted: Bool
public var pixelfedAccount: AccountData?
init(accountId: String, boostedStatusesMuted: Bool, pixelfedAccount: AccountData? = nil) {
self.accountId = accountId
self.boostedStatusesMuted = boostedStatusesMuted
self.pixelfedAccount = pixelfedAccount
}
}
extension AccountRelationship: Identifiable {
}

View File

@ -0,0 +1,81 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import PixelfedKit
import SwiftData
class AccountRelationshipHandler {
public static let shared = AccountRelationshipHandler()
private init() { }
func getAccountRelationships(for accountId: String, modelContext: ModelContext) -> [AccountRelationship] {
do {
var fetchDescriptor = FetchDescriptor<AccountRelationship>(
predicate: #Predicate { $0.pixelfedAccount?.id == accountId }
)
fetchDescriptor.includePendingChanges = true
return try modelContext.fetch(fetchDescriptor)
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching account relationship (isBoostedMutedForAccount).")
return []
}
}
/// Check if boosted statuses from given account are muted.
func isBoostedStatusesMuted(accountId: String, status: Status, modelContext: ModelContext) -> Bool {
if status.reblog == nil {
return false
}
let accountRelationship = self.getAccountRelationship(for: accountId, relation: status.account.id, modelContext: modelContext)
return accountRelationship?.boostedStatusesMuted ?? false
}
func isBoostedStatusesMuted(for accountId: String, relation relationAccountId: String, modelContext: ModelContext) -> Bool {
let accountRelationship = self.getAccountRelationship(for: accountId, relation: relationAccountId, modelContext: modelContext)
return accountRelationship?.boostedStatusesMuted ?? false
}
func setBoostedStatusesMuted(for accountId: String, relation relationAccountId: String, boostedStatusesMuted: Bool, modelContext: ModelContext) {
var accountRelationship = self.getAccountRelationship(for: accountId, relation: relationAccountId, modelContext: modelContext)
if accountRelationship == nil {
guard let accountDataFromDb = AccountDataHandler.shared.getAccountData(accountId: accountId, modelContext: modelContext) else {
return
}
let newAccountRelationship = AccountRelationship(accountId: relationAccountId, boostedStatusesMuted: false, pixelfedAccount: accountDataFromDb)
modelContext.insert(newAccountRelationship)
accountDataFromDb.accountRelationships.append(newAccountRelationship)
accountRelationship = newAccountRelationship
}
accountRelationship?.boostedStatusesMuted = boostedStatusesMuted
do {
try modelContext.save()
} catch {
CoreDataError.shared.handle(error, message: "Error during saving boosted muted statuses.")
}
}
private func getAccountRelationship(for accountId: String, relation relationAccountId: String, modelContext: ModelContext) -> AccountRelationship? {
do {
var fetchDescriptor = FetchDescriptor<AccountRelationship>(
predicate: #Predicate { $0.accountId == relationAccountId && $0.pixelfedAccount?.id == accountId }
)
fetchDescriptor.fetchLimit = 1
fetchDescriptor.includePendingChanges = true
return try modelContext.fetch(fetchDescriptor).first
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching account relationship (isBoostedMutedForAccount).")
return nil
}
}
}

View File

@ -1,12 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
@objc(ApplicationSettings)
public class ApplicationSettings: NSManagedObject {
}

View File

@ -1,44 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
extension ApplicationSettings {
@nonobjc public class func fetchRequest() -> NSFetchRequest<ApplicationSettings> {
return NSFetchRequest<ApplicationSettings>(entityName: "ApplicationSettings")
}
@NSManaged public var currentAccount: String?
@NSManaged public var theme: Int32
@NSManaged public var tintColor: Int32
@NSManaged public var avatarShape: Int32
@NSManaged public var activeIcon: String
@NSManaged public var lastRefreshTokens: Date
@NSManaged public var hapticTabSelectionEnabled: Bool
@NSManaged public var hapticRefreshEnabled: Bool
@NSManaged public var hapticButtonPressEnabled: Bool
@NSManaged public var hapticAnimationEnabled: Bool
@NSManaged public var hapticNotificationEnabled: Bool
@NSManaged public var showSensitive: Bool
@NSManaged public var showPhotoDescription: Bool
@NSManaged public var menuPosition: Int32
@NSManaged public var showAvatarsOnTimeline: Bool
@NSManaged public var showFavouritesOnTimeline: Bool
@NSManaged public var showAltIconOnTimeline: Bool
@NSManaged public var warnAboutMissingAlt: Bool
@NSManaged public var showGridOnUserProfile: Bool
@NSManaged public var customNavigationMenuItem1: Int32
@NSManaged public var customNavigationMenuItem2: Int32
@NSManaged public var customNavigationMenuItem3: Int32
}
extension ApplicationSettings: Identifiable {
}

View File

@ -0,0 +1,97 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import SwiftData
import EnvironmentKit
@Model final public class ApplicationSettings {
public var currentAccount: String? = nil
public var theme: Int32 = Int32(Theme.system.rawValue)
public var tintColor: Int32 = Int32(TintColor.accentColor2.rawValue)
public var avatarShape: Int32 = Int32(AvatarShape.circle.rawValue)
public var activeIcon: String = "Default"
public var lastRefreshTokens: Date = Date.distantPast
public var hapticTabSelectionEnabled: Bool = true
public var hapticRefreshEnabled: Bool = true
public var hapticButtonPressEnabled: Bool = true
public var hapticAnimationEnabled: Bool = true
public var hapticNotificationEnabled: Bool = true
public var showSensitive: Bool = false
public var showApplicationBadge: Bool = false
public var showPhotoDescription: Bool = false
public var menuPosition: Int32 = Int32(MenuPosition.top.rawValue)
public var showAvatarsOnTimeline: Bool = false
public var showFavouritesOnTimeline: Bool = false
public var showAltIconOnTimeline: Bool = false
public var warnAboutMissingAlt: Bool = true
public var showGridOnUserProfile: Bool = false
public var showReboostedStatuses: Bool = false
public var hideStatusesWithoutAlt: Bool = false
public var customNavigationMenuItem1: Int32 = 1
public var customNavigationMenuItem2: Int32 = 2
public var customNavigationMenuItem3: Int32 = 5
init(
currentAccount: String? = nil,
theme: Int32 = Int32(Theme.system.rawValue),
tintColor: Int32 = Int32(TintColor.accentColor2.rawValue),
avatarShape: Int32 = Int32(AvatarShape.circle.rawValue),
activeIcon: String = "Default",
lastRefreshTokens: Date = Date.distantPast,
hapticTabSelectionEnabled: Bool = true,
hapticRefreshEnabled: Bool = true,
hapticButtonPressEnabled: Bool = true,
hapticAnimationEnabled: Bool = true,
hapticNotificationEnabled: Bool = true,
showSensitive: Bool = false,
showApplicationBadge: Bool = false,
showPhotoDescription: Bool = false,
menuPosition: Int32 = Int32(MenuPosition.top.rawValue),
showAvatarsOnTimeline: Bool = false,
showFavouritesOnTimeline: Bool = false,
showAltIconOnTimeline: Bool = false,
warnAboutMissingAlt: Bool = true,
showGridOnUserProfile: Bool = false,
showReboostedStatuses: Bool = false,
hideStatusesWithoutAlt: Bool = false,
customNavigationMenuItem1: Int32 = 1,
customNavigationMenuItem2: Int32 = 2,
customNavigationMenuItem3: Int32 = 5
) {
self.currentAccount = currentAccount
self.theme = theme
self.tintColor = tintColor
self.avatarShape = avatarShape
self.activeIcon = activeIcon
self.lastRefreshTokens = lastRefreshTokens
self.hapticTabSelectionEnabled = hapticTabSelectionEnabled
self.hapticRefreshEnabled = hapticRefreshEnabled
self.hapticButtonPressEnabled = hapticButtonPressEnabled
self.hapticAnimationEnabled = hapticAnimationEnabled
self.hapticNotificationEnabled = hapticNotificationEnabled
self.showSensitive = showSensitive
self.showApplicationBadge = showApplicationBadge
self.showPhotoDescription = showPhotoDescription
self.menuPosition = menuPosition
self.showAvatarsOnTimeline = showAvatarsOnTimeline
self.showFavouritesOnTimeline = showFavouritesOnTimeline
self.showAltIconOnTimeline = showAltIconOnTimeline
self.warnAboutMissingAlt = warnAboutMissingAlt
self.showGridOnUserProfile = showGridOnUserProfile
self.showReboostedStatuses = showReboostedStatuses
self.hideStatusesWithoutAlt = hideStatusesWithoutAlt
self.customNavigationMenuItem1 = customNavigationMenuItem1
self.customNavigationMenuItem2 = customNavigationMenuItem2
self.customNavigationMenuItem3 = customNavigationMenuItem3
}
}
extension ApplicationSettings: Identifiable {
}

View File

@ -5,20 +5,21 @@
//
import Foundation
import CoreData
import EnvironmentKit
import SwiftData
class ApplicationSettingsHandler {
public static let shared = ApplicationSettingsHandler()
private init() { }
func get(viewContext: NSManagedObjectContext? = nil) -> ApplicationSettings {
func get(modelContext: ModelContext) -> ApplicationSettings {
var settingsList: [ApplicationSettings] = []
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = ApplicationSettings.fetchRequest()
do {
settingsList = try context.fetch(fetchRequest)
var fetchDescriptor = FetchDescriptor<ApplicationSettings>()
fetchDescriptor.includePendingChanges = true
settingsList = try modelContext.fetch(fetchDescriptor)
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching application settings.")
}
@ -26,18 +27,23 @@ class ApplicationSettingsHandler {
if let settings = settingsList.first {
return settings
} else {
let settings = self.createApplicationSettingsEntity(viewContext: context)
settings.avatarShape = Int32(AvatarShape.circle.rawValue)
settings.theme = Int32(Theme.system.rawValue)
settings.tintColor = Int32(TintColor.accentColor2.rawValue)
CoreDataHandler.shared.save(viewContext: context)
do {
let settings = ApplicationSettings()
modelContext.insert(settings)
return settings
try modelContext.save()
return settings
} catch {
CoreDataError.shared.handle(error, message: "Error during saving new application settings.")
let settings = ApplicationSettings()
return settings
}
}
}
func update(applicationState: ApplicationState) {
let defaultSettings = ApplicationSettingsHandler.shared.get()
func update(applicationState: ApplicationState, modelContext: ModelContext) {
let defaultSettings = ApplicationSettingsHandler.shared.get(modelContext: modelContext)
if let tintColor = TintColor(rawValue: Int(defaultSettings.tintColor)) {
applicationState.tintColor = tintColor
@ -59,6 +65,9 @@ class ApplicationSettingsHandler {
applicationState.showAltIconOnTimeline = defaultSettings.showAltIconOnTimeline
applicationState.warnAboutMissingAlt = defaultSettings.warnAboutMissingAlt
applicationState.showGridOnUserProfile = defaultSettings.showGridOnUserProfile
applicationState.showReboostedStatuses = defaultSettings.showReboostedStatuses
applicationState.hideStatusesWithoutAlt = defaultSettings.hideStatusesWithoutAlt
applicationState.showApplicationBadge = defaultSettings.showApplicationBadge
if let menuPosition = MenuPosition(rawValue: Int(defaultSettings.menuPosition)) {
applicationState.menuPosition = menuPosition
@ -71,134 +80,147 @@ class ApplicationSettingsHandler {
applicationState.hapticNotificationEnabled = defaultSettings.hapticNotificationEnabled
}
func set(accountId: String?) {
let defaultSettings = self.get()
func set(accountId: String?, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.currentAccount = accountId
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(tintColor: TintColor) {
let defaultSettings = self.get()
func set(tintColor: TintColor, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.tintColor = Int32(tintColor.rawValue)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(theme: Theme) {
let defaultSettings = self.get()
func set(theme: Theme, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.theme = Int32(theme.rawValue)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(avatarShape: AvatarShape) {
let defaultSettings = self.get()
func set(avatarShape: AvatarShape, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.avatarShape = Int32(avatarShape.rawValue)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(hapticTabSelectionEnabled: Bool) {
let defaultSettings = self.get()
func set(hapticTabSelectionEnabled: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.hapticTabSelectionEnabled = hapticTabSelectionEnabled
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(hapticRefreshEnabled: Bool) {
let defaultSettings = self.get()
func set(hapticRefreshEnabled: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.hapticRefreshEnabled = hapticRefreshEnabled
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(hapticAnimationEnabled: Bool) {
let defaultSettings = self.get()
func set(hapticAnimationEnabled: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.hapticAnimationEnabled = hapticAnimationEnabled
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(hapticNotificationEnabled: Bool) {
let defaultSettings = self.get()
func set(hapticNotificationEnabled: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.hapticNotificationEnabled = hapticNotificationEnabled
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(hapticButtonPressEnabled: Bool) {
let defaultSettings = self.get()
func set(hapticButtonPressEnabled: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.hapticButtonPressEnabled = hapticButtonPressEnabled
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(showSensitive: Bool) {
let defaultSettings = self.get()
func set(showSensitive: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showSensitive = showSensitive
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(showApplicationBadge: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showApplicationBadge = showApplicationBadge
try? modelContext.save()
}
func set(showPhotoDescription: Bool) {
let defaultSettings = self.get()
func set(showPhotoDescription: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showPhotoDescription = showPhotoDescription
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(activeIcon: String) {
let defaultSettings = self.get()
func set(activeIcon: String, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.activeIcon = activeIcon
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(menuPosition: MenuPosition) {
let defaultSettings = self.get()
func set(menuPosition: MenuPosition, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.menuPosition = Int32(menuPosition.rawValue)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(showAvatarsOnTimeline: Bool) {
let defaultSettings = self.get()
func set(showAvatarsOnTimeline: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showAvatarsOnTimeline = showAvatarsOnTimeline
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(showFavouritesOnTimeline: Bool) {
let defaultSettings = self.get()
func set(showFavouritesOnTimeline: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showFavouritesOnTimeline = showFavouritesOnTimeline
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(showAltIconOnTimeline: Bool) {
let defaultSettings = self.get()
func set(showAltIconOnTimeline: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showAltIconOnTimeline = showAltIconOnTimeline
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(warnAboutMissingAlt: Bool) {
let defaultSettings = self.get()
func set(warnAboutMissingAlt: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.warnAboutMissingAlt = warnAboutMissingAlt
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(customNavigationMenuItem1: Int) {
let defaultSettings = self.get()
func set(customNavigationMenuItem1: Int, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.customNavigationMenuItem1 = Int32(customNavigationMenuItem1)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(customNavigationMenuItem2: Int) {
let defaultSettings = self.get()
func set(customNavigationMenuItem2: Int, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.customNavigationMenuItem2 = Int32(customNavigationMenuItem2)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(customNavigationMenuItem3: Int) {
let defaultSettings = self.get()
func set(customNavigationMenuItem3: Int, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.customNavigationMenuItem3 = Int32(customNavigationMenuItem3)
CoreDataHandler.shared.save()
try? modelContext.save()
}
func set(showGridOnUserProfile: Bool) {
let defaultSettings = self.get()
func set(showGridOnUserProfile: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showGridOnUserProfile = showGridOnUserProfile
CoreDataHandler.shared.save()
try? modelContext.save()
}
private func createApplicationSettingsEntity(viewContext: NSManagedObjectContext? = nil) -> ApplicationSettings {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
return ApplicationSettings(context: context)
func set(showReboostedStatuses: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.showReboostedStatuses = showReboostedStatuses
try? modelContext.save()
}
func set(hideStatusesWithoutAlt: Bool, modelContext: ModelContext) {
let defaultSettings = self.get(modelContext: modelContext)
defaultSettings.hideStatusesWithoutAlt = hideStatusesWithoutAlt
try? modelContext.save()
}
}

View File

@ -1,30 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import PixelfedKit
extension AttachmentData {
func copyFrom(_ attachment: MediaAttachment) {
self.id = attachment.id
self.url = attachment.url
self.blurhash = attachment.blurhash
self.previewUrl = attachment.previewUrl
self.remoteUrl = attachment.remoteUrl
self.text = attachment.description
self.type = attachment.type.rawValue
// We can set image width only when it wasn't previusly recalculated.
if let width = (attachment.meta as? ImageMetadata)?.original?.width, self.metaImageWidth <= 0 && width > 0 {
self.metaImageWidth = Int32(width)
}
// We can set image height only when it wasn't previusly recalculated.
if let height = (attachment.meta as? ImageMetadata)?.original?.height, self.metaImageHeight <= 0 && height > 0 {
self.metaImageHeight = Int32(height)
}
}
}

View File

@ -1,13 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
extension AttachmentData: Comparable {
public static func < (lhs: AttachmentData, rhs: AttachmentData) -> Bool {
lhs.id < rhs.id
}
}

View File

@ -1,12 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
@objc(AttachmentData)
public class AttachmentData: NSManagedObject {
}

View File

@ -1,36 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
extension AttachmentData {
@nonobjc public class func fetchRequest() -> NSFetchRequest<AttachmentData> {
return NSFetchRequest<AttachmentData>(entityName: "AttachmentData")
}
@NSManaged public var blurhash: String?
@NSManaged public var data: Data?
@NSManaged public var exifCamera: String?
@NSManaged public var exifCreatedDate: String?
@NSManaged public var exifExposure: String?
@NSManaged public var exifLens: String?
@NSManaged public var id: String
@NSManaged public var previewUrl: URL?
@NSManaged public var remoteUrl: URL?
@NSManaged public var statusId: String
@NSManaged public var text: String?
@NSManaged public var type: String
@NSManaged public var url: URL
@NSManaged public var metaImageWidth: Int32
@NSManaged public var metaImageHeight: Int32
@NSManaged public var order: Int32
@NSManaged public var statusRelation: StatusData?
}
extension AttachmentData: Identifiable {
}

View File

@ -1,13 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
extension AttachmentData {
func isFaulty() -> Bool {
return self.isDeleted || self.isFault
}
}

View File

@ -1,24 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
extension [AttachmentData] {
func getHighestImage() -> AttachmentData? {
var attachment = self.first
var imgHeight = 0.0
for item in self {
let attachmentheight = Double(item.metaImageHeight)
if attachmentheight > imgHeight {
attachment = item
imgHeight = attachmentheight
}
}
return attachment
}
}

View File

@ -1,18 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
class AttachmentDataHandler {
public static let shared = AttachmentDataHandler()
private init() { }
func createAttachmnentDataEntity(viewContext: NSManagedObjectContext? = nil) -> AttachmentData {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
return AttachmentData(context: context)
}
}

View File

@ -5,12 +5,14 @@
//
import Foundation
import OSLog
import EnvironmentKit
public class CoreDataError {
public static let shared = CoreDataError()
private init() { }
public func handle(_ error: Error, message: String) {
print("Error ['\(message)']: \(error.localizedDescription)")
Logger.main.error("Error ['\(message)']: \(error.localizedDescription)")
}
}

View File

@ -1,98 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import CoreData
import EnvironmentKit
public class CoreDataHandler {
public static let shared = CoreDataHandler()
lazy var container: NSPersistentContainer = {
let container = NSPersistentContainer(name: AppConstants.coreDataPersistantContainerName)
let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.dev.mczachurski.vernissage")!
.appendingPathComponent("Data.sqlite")
var defaultURL: URL?
if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
defaultURL = FileManager.default.fileExists(atPath: url.path) ? url : nil
}
if defaultURL == nil {
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
}
container.loadPersistentStores(completionHandler: { [unowned container] (_, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate.
// You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
// Migrate old store do current (shared between app and widget)
if let url = defaultURL, url.absoluteString != storeURL.absoluteString {
let coordinator = container.persistentStoreCoordinator
if let oldStore = coordinator.persistentStore(for: url) {
// Migration process.
do {
try coordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
} catch {
print(error.localizedDescription)
}
// Delete old store.
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: { url in
do {
try FileManager.default.removeItem(at: url)
} catch {
print(error.localizedDescription)
}
})
}
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
return container
}()
public func newBackgroundContext() -> NSManagedObjectContext {
self.container.newBackgroundContext()
}
public func save(viewContext: NSManagedObjectContext? = nil) {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
if context.hasChanges {
context.performAndWait {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate.
// You should not use this function in a shipping application, although it may be useful during development.
#if DEBUG
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
#else
CoreDataError.shared.handle(error, message: "An error occurred while writing the data.")
#endif
}
}
}
}
}

View File

@ -1,19 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
extension StatusData {
func attachments() -> [AttachmentData] {
guard let attachments = self.attachmentsRelation else {
return []
}
return attachments.sorted(by: { lhs, rhs in
lhs.order < rhs.order
})
}
}

View File

@ -1,12 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
@objc(StatusData)
public class StatusData: NSManagedObject {
}

View File

@ -1,68 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
extension StatusData {
@nonobjc public class func fetchRequest() -> NSFetchRequest<StatusData> {
return NSFetchRequest<StatusData>(entityName: "StatusData")
}
@NSManaged public var accountAvatar: URL?
@NSManaged public var accountDisplayName: String?
@NSManaged public var accountId: String
@NSManaged public var accountUsername: String
@NSManaged public var applicationName: String?
@NSManaged public var applicationWebsite: URL?
@NSManaged public var bookmarked: Bool
@NSManaged public var content: String
@NSManaged public var createdAt: String
@NSManaged public var favourited: Bool
@NSManaged public var favouritesCount: Int32
@NSManaged public var id: String
@NSManaged public var inReplyToAccount: String?
@NSManaged public var inReplyToId: String?
@NSManaged public var muted: Bool
@NSManaged public var pinned: Bool
@NSManaged public var reblogged: Bool
@NSManaged public var reblogsCount: Int32
@NSManaged public var repliesCount: Int32
@NSManaged public var sensitive: Bool
@NSManaged public var spoilerText: String?
@NSManaged public var uri: String?
@NSManaged public var url: URL?
@NSManaged public var visibility: String
@NSManaged public var attachmentsRelation: Set<AttachmentData>?
@NSManaged public var pixelfedAccount: AccountData
@NSManaged public var rebloggedStatusId: String?
@NSManaged public var rebloggedAccountAvatar: URL?
@NSManaged public var rebloggedAccountDisplayName: String?
@NSManaged public var rebloggedAccountId: String?
@NSManaged public var rebloggedAccountUsername: String?
}
// MARK: Generated accessors for attachmentRelation
extension StatusData {
@objc(addAttachmentsRelationObject:)
@NSManaged public func addToAttachmentsRelation(_ value: AttachmentData)
@objc(removeAttachmentsRelationObject:)
@NSManaged public func removeFromAttachmentsRelation(_ value: AttachmentData)
@objc(addAttachmentsRelation:)
@NSManaged public func addToAttachmentsRelation(_ values: NSSet)
@objc(removeAttachmentsRelation:)
@NSManaged public func removeFromAttachmentsRelation(_ values: NSSet)
}
extension StatusData: Identifiable {
}

View File

@ -1,13 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
extension StatusData {
func isFaulty() -> Bool {
return self.isDeleted || self.isFault
}
}

View File

@ -1,80 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import PixelfedKit
extension StatusData {
func copyFrom(_ status: Status) {
if let reblog = status.reblog {
self.copyFrom(reblog)
self.rebloggedStatusId = status.id
self.rebloggedAccountAvatar = status.account.avatar
self.rebloggedAccountDisplayName = status.account.displayName
self.rebloggedAccountId = status.account.id
self.rebloggedAccountUsername = status.account.acct
} else {
self.id = status.id
self.createdAt = status.createdAt
self.accountAvatar = status.account.avatar
self.accountDisplayName = status.account.displayName
self.accountId = status.account.id
self.accountUsername = status.account.acct
self.applicationName = status.application?.name
self.applicationWebsite = status.application?.website
self.bookmarked = status.bookmarked
self.content = status.content.htmlValue
self.favourited = status.favourited
self.favouritesCount = Int32(status.favouritesCount)
self.inReplyToAccount = status.inReplyToAccount
self.inReplyToId = status.inReplyToId
self.muted = status.muted
self.pinned = status.pinned
self.reblogged = status.reblogged
self.reblogsCount = Int32(status.reblogsCount)
self.repliesCount = Int32(status.repliesCount)
self.sensitive = status.sensitive
self.spoilerText = status.spoilerText
self.uri = status.uri
self.url = status.url
self.visibility = status.visibility.rawValue
}
}
func updateFrom(_ status: Status) {
if let reblog = status.reblog {
self.updateFrom(reblog)
self.rebloggedAccountAvatar = status.account.avatar
self.rebloggedAccountDisplayName = status.account.displayName
self.rebloggedAccountId = status.account.id
self.rebloggedAccountUsername = status.account.acct
} else {
self.accountAvatar = status.account.avatar
self.accountDisplayName = status.account.displayName
self.accountUsername = status.account.acct
self.applicationName = status.application?.name
self.applicationWebsite = status.application?.website
self.bookmarked = status.bookmarked
self.content = status.content.htmlValue
self.favourited = status.favourited
self.favouritesCount = Int32(status.favouritesCount)
self.inReplyToAccount = status.inReplyToAccount
self.inReplyToId = status.inReplyToId
self.muted = status.muted
self.pinned = status.pinned
self.reblogged = status.reblogged
self.reblogsCount = Int32(status.reblogsCount)
self.repliesCount = Int32(status.repliesCount)
self.sensitive = status.sensitive
self.spoilerText = status.spoilerText
self.uri = status.uri
self.url = status.url
self.visibility = status.visibility.rawValue
}
}
}

View File

@ -1,136 +0,0 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import CoreData
import PixelfedKit
class StatusDataHandler {
public static let shared = StatusDataHandler()
private init() { }
func getAllStatuses(accountId: String, viewContext: NSManagedObjectContext? = nil) -> [StatusData] {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = StatusData.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format: "pixelfedAccount.id = %@", accountId)
do {
return try context.fetch(fetchRequest)
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching status (getStatusData).")
return []
}
}
func getAllOlderStatuses(accountId: String, statusId: String, viewContext: NSManagedObjectContext? = nil) -> [StatusData] {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = StatusData.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
let predicate1 = NSPredicate(format: "id < %@", statusId)
let predicate2 = NSPredicate(format: "pixelfedAccount.id = %@", accountId)
fetchRequest.predicate = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1, predicate2])
do {
return try context.fetch(fetchRequest)
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching status (getStatusData).")
return []
}
}
func getStatusData(accountId: String, statusId: String, viewContext: NSManagedObjectContext? = nil) -> StatusData? {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = StatusData.fetchRequest()
fetchRequest.fetchLimit = 1
let predicate1 = NSPredicate(format: "id = %@", statusId)
let predicate2 = NSPredicate(format: "pixelfedAccount.id = %@", accountId)
fetchRequest.predicate = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1, predicate2])
do {
return try context.fetch(fetchRequest).first
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching status (getStatusData).")
return nil
}
}
func getMaximumStatus(accountId: String, viewContext: NSManagedObjectContext? = nil) -> StatusData? {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = StatusData.fetchRequest()
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "id", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format: "pixelfedAccount.id = %@", accountId)
do {
let statuses = try context.fetch(fetchRequest)
return statuses.first
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching maximum status (getMaximumStatus).")
return nil
}
}
func getMinimumStatus(accountId: String, viewContext: NSManagedObjectContext? = nil) -> StatusData? {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
let fetchRequest = StatusData.fetchRequest()
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format: "pixelfedAccount.id = %@", accountId)
do {
let statuses = try context.fetch(fetchRequest)
return statuses.first
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching minimum status (getMinimumtatus).")
return nil
}
}
func remove(accountId: String, statusId: String, viewContext: NSManagedObjectContext? = nil) {
let status = self.getStatusData(accountId: accountId, statusId: statusId)
guard let status else {
return
}
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
context.delete(status)
do {
try context.save()
} catch {
CoreDataError.shared.handle(error, message: "Error during deleting status (remove).")
}
}
func setFavourited(accountId: String, statusId: String) {
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
if let statusData = self.getStatusData(accountId: accountId, statusId: statusId, viewContext: backgroundContext) {
statusData.favourited = true
CoreDataHandler.shared.save(viewContext: backgroundContext)
}
}
func createStatusDataEntity(viewContext: NSManagedObjectContext? = nil) -> StatusData {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
return StatusData(context: context)
}
}

View File

@ -0,0 +1,30 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import OSLog
import EnvironmentKit
import SwiftData
public class SwiftDataHandler {
public static let shared = SwiftDataHandler()
lazy var sharedModelContainer: ModelContainer = {
let schema = Schema([
ApplicationSettings.self,
AccountData.self,
ViewedStatus.self,
AccountRelationship.self
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
}

View File

@ -1,8 +1,5 @@
<?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>_XCCurrentVersionName</key>
<string>Vernissage-014.xcdatamodel</string>
</dict>
<dict/>
</plist>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22222" systemVersion="23A344" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
<attribute name="accessToken" optional="YES" attributeType="String"/>
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" optional="YES" attributeType="URI"/>
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
<attribute name="clientId" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="clientVapidKey" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="displayName" optional="YES" attributeType="String"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/>
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="refreshToken" optional="YES" attributeType="String"/>
<attribute name="serverUrl" attributeType="URI"/>
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="username" attributeType="String"/>
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
</entity>
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
<attribute name="activeIcon" attributeType="String" defaultValueString="Default"/>
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="currentAccount" optional="YES" attributeType="String"/>
<attribute name="customNavigationMenuItem1" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem2" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem3" attributeType="Integer 32" defaultValueString="5" usesScalarValueType="YES"/>
<attribute name="hapticAnimationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticButtonPressEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticNotificationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticRefreshEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticTabSelectionEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="lastRefreshTokens" attributeType="Date" defaultDateTimeInterval="694256400" usesScalarValueType="NO"/>
<attribute name="menuPosition" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="showAltIconOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showAvatarsOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showFavouritesOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showGridOnUserProfile" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showPhotoDescription" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showReboostedStatuses" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="warnAboutMissingAlt" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
</entity>
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
<attribute name="exifCamera" optional="YES" attributeType="String"/>
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
<attribute name="exifExposure" optional="YES" attributeType="String"/>
<attribute name="exifLens" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="order" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
<attribute name="statusId" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="type" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
</entity>
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
<attribute name="accountId" attributeType="String"/>
<attribute name="accountUsername" optional="YES" attributeType="String"/>
<attribute name="applicationName" optional="YES" attributeType="String"/>
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="visibility" attributeType="String"/>
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
</entity>
</model>

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22222" systemVersion="23A344" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
<attribute name="accessToken" optional="YES" attributeType="String"/>
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" optional="YES" attributeType="URI"/>
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
<attribute name="clientId" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="clientVapidKey" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="displayName" optional="YES" attributeType="String"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/>
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="refreshToken" optional="YES" attributeType="String"/>
<attribute name="serverUrl" attributeType="URI"/>
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="username" attributeType="String"/>
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
<relationship name="viewedStatuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="ViewedStatus" inverseName="pixelfedAccount" inverseEntity="ViewedStatus"/>
</entity>
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
<attribute name="activeIcon" attributeType="String" defaultValueString="Default"/>
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="currentAccount" optional="YES" attributeType="String"/>
<attribute name="customNavigationMenuItem1" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem2" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem3" attributeType="Integer 32" defaultValueString="5" usesScalarValueType="YES"/>
<attribute name="hapticAnimationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticButtonPressEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticNotificationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticRefreshEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticTabSelectionEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="lastRefreshTokens" attributeType="Date" defaultDateTimeInterval="694256400" usesScalarValueType="NO"/>
<attribute name="menuPosition" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="showAltIconOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showAvatarsOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showFavouritesOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showGridOnUserProfile" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showPhotoDescription" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showReboostedStatuses" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="warnAboutMissingAlt" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
</entity>
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
<attribute name="exifCamera" optional="YES" attributeType="String"/>
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
<attribute name="exifExposure" optional="YES" attributeType="String"/>
<attribute name="exifLens" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="order" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
<attribute name="statusId" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="type" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
</entity>
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
<attribute name="accountId" attributeType="String"/>
<attribute name="accountUsername" optional="YES" attributeType="String"/>
<attribute name="applicationName" optional="YES" attributeType="String"/>
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="visibility" attributeType="String"/>
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
</entity>
<entity name="ViewedStatus" representedClassName="ViewedStatus" syncable="YES">
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="viewedStatuses" inverseEntity="AccountData"/>
</entity>
</model>

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22222" systemVersion="23A344" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
<attribute name="accessToken" optional="YES" attributeType="String"/>
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" optional="YES" attributeType="URI"/>
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
<attribute name="clientId" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="clientVapidKey" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="displayName" optional="YES" attributeType="String"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/>
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="refreshToken" optional="YES" attributeType="String"/>
<attribute name="serverUrl" attributeType="URI"/>
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="username" attributeType="String"/>
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
<relationship name="viewedStatuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="ViewedStatus" inverseName="pixelfedAccount" inverseEntity="ViewedStatus"/>
</entity>
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
<attribute name="activeIcon" attributeType="String" defaultValueString="Default"/>
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="currentAccount" optional="YES" attributeType="String"/>
<attribute name="customNavigationMenuItem1" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem2" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem3" attributeType="Integer 32" defaultValueString="5" usesScalarValueType="YES"/>
<attribute name="hapticAnimationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticButtonPressEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticNotificationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticRefreshEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticTabSelectionEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="lastRefreshTokens" attributeType="Date" defaultDateTimeInterval="694256400" usesScalarValueType="NO"/>
<attribute name="menuPosition" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="showAltIconOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showAvatarsOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showFavouritesOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showGridOnUserProfile" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showPhotoDescription" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showReboostedStatuses" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="warnAboutMissingAlt" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
</entity>
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
<attribute name="exifCamera" optional="YES" attributeType="String"/>
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
<attribute name="exifExposure" optional="YES" attributeType="String"/>
<attribute name="exifLens" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="order" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
<attribute name="statusId" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="type" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
</entity>
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
<attribute name="accountId" attributeType="String"/>
<attribute name="accountUsername" optional="YES" attributeType="String"/>
<attribute name="applicationName" optional="YES" attributeType="String"/>
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="visibility" attributeType="String"/>
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
</entity>
<entity name="ViewedStatus" representedClassName="ViewedStatus" syncable="YES">
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<attribute name="reblogId" optional="YES" attributeType="String"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="viewedStatuses" inverseEntity="AccountData"/>
</entity>
</model>

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22222" systemVersion="23A344" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
<attribute name="accessToken" optional="YES" attributeType="String"/>
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" optional="YES" attributeType="URI"/>
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
<attribute name="clientId" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="clientVapidKey" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="displayName" optional="YES" attributeType="String"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/>
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="refreshToken" optional="YES" attributeType="String"/>
<attribute name="serverUrl" attributeType="URI"/>
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="username" attributeType="String"/>
<relationship name="accountRelationships" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AccountRelationship" inverseName="pixelfedAccount" inverseEntity="AccountRelationship"/>
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
<relationship name="viewedStatuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="ViewedStatus" inverseName="pixelfedAccount" inverseEntity="ViewedStatus"/>
</entity>
<entity name="AccountRelationship" representedClassName="AccountRelationship" syncable="YES">
<attribute name="accountId" attributeType="String"/>
<attribute name="boostedStatusesMuted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<relationship name="pixelfedAccount" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="accountRelationships" inverseEntity="AccountData"/>
</entity>
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
<attribute name="activeIcon" attributeType="String" defaultValueString="Default"/>
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="currentAccount" optional="YES" attributeType="String"/>
<attribute name="customNavigationMenuItem1" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem2" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem3" attributeType="Integer 32" defaultValueString="5" usesScalarValueType="YES"/>
<attribute name="hapticAnimationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticButtonPressEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticNotificationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticRefreshEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticTabSelectionEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="lastRefreshTokens" attributeType="Date" defaultDateTimeInterval="694256400" usesScalarValueType="NO"/>
<attribute name="menuPosition" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="showAltIconOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showAvatarsOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showFavouritesOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showGridOnUserProfile" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showPhotoDescription" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showReboostedStatuses" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="warnAboutMissingAlt" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
</entity>
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
<attribute name="exifCamera" optional="YES" attributeType="String"/>
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
<attribute name="exifExposure" optional="YES" attributeType="String"/>
<attribute name="exifLens" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="order" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
<attribute name="statusId" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="type" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
</entity>
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
<attribute name="accountId" attributeType="String"/>
<attribute name="accountUsername" optional="YES" attributeType="String"/>
<attribute name="applicationName" optional="YES" attributeType="String"/>
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="visibility" attributeType="String"/>
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
</entity>
<entity name="ViewedStatus" representedClassName="ViewedStatus" syncable="YES">
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<attribute name="reblogId" optional="YES" attributeType="String"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="viewedStatuses" inverseEntity="AccountData"/>
</entity>
</model>

View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22222" systemVersion="23A344" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
<attribute name="accessToken" optional="YES" attributeType="String"/>
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" optional="YES" attributeType="URI"/>
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
<attribute name="clientId" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="clientVapidKey" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="displayName" optional="YES" attributeType="String"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/>
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="refreshToken" optional="YES" attributeType="String"/>
<attribute name="serverUrl" attributeType="URI"/>
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="username" attributeType="String"/>
<relationship name="accountRelationships" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AccountRelationship" inverseName="pixelfedAccount" inverseEntity="AccountRelationship"/>
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
<relationship name="viewedStatuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="ViewedStatus" inverseName="pixelfedAccount" inverseEntity="ViewedStatus"/>
</entity>
<entity name="AccountRelationship" representedClassName="AccountRelationship" syncable="YES">
<attribute name="accountId" attributeType="String"/>
<attribute name="boostedStatusesMuted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<relationship name="pixelfedAccount" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="accountRelationships" inverseEntity="AccountData"/>
</entity>
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
<attribute name="activeIcon" attributeType="String" defaultValueString="Default"/>
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="currentAccount" optional="YES" attributeType="String"/>
<attribute name="customNavigationMenuItem1" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem2" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="customNavigationMenuItem3" attributeType="Integer 32" defaultValueString="5" usesScalarValueType="YES"/>
<attribute name="hapticAnimationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticButtonPressEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticNotificationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticRefreshEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticTabSelectionEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hideStatusesWithoutAlt" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="lastRefreshTokens" attributeType="Date" defaultDateTimeInterval="694256400" usesScalarValueType="NO"/>
<attribute name="menuPosition" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="showAltIconOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showAvatarsOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showFavouritesOnTimeline" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showGridOnUserProfile" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showPhotoDescription" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showReboostedStatuses" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
<attribute name="warnAboutMissingAlt" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
</entity>
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
<attribute name="exifCamera" optional="YES" attributeType="String"/>
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
<attribute name="exifExposure" optional="YES" attributeType="String"/>
<attribute name="exifLens" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="order" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
<attribute name="statusId" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="type" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
</entity>
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
<attribute name="accountId" attributeType="String"/>
<attribute name="accountUsername" optional="YES" attributeType="String"/>
<attribute name="applicationName" optional="YES" attributeType="String"/>
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="visibility" attributeType="String"/>
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
</entity>
<entity name="ViewedStatus" representedClassName="ViewedStatus" syncable="YES">
<attribute name="date" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<attribute name="reblogId" optional="YES" attributeType="String"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="viewedStatuses" inverseEntity="AccountData"/>
</entity>
</model>

View File

@ -0,0 +1,26 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import SwiftData
@Model final public class ViewedStatus {
@Attribute(.unique) public var id: String
public var reblogId: String?
public var date: Date
public var pixelfedAccount: AccountData?
init(id: String, reblogId: String? = nil, date: Date, pixelfedAccount: AccountData? = nil) {
self.id = id
self.reblogId = reblogId
self.date = date
self.pixelfedAccount = pixelfedAccount
}
}
extension ViewedStatus: Identifiable {
}

View File

@ -0,0 +1,106 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import Foundation
import SwiftData
import PixelfedKit
class ViewedStatusHandler {
public static let shared = ViewedStatusHandler()
private init() { }
/// Append new visible statuses to database.
func append(contentsOf statuses: [Status], accountId: String, modelContext: ModelContext) throws {
guard let accountDataFromDb = AccountDataHandler.shared.getAccountData(accountId: accountId, modelContext: modelContext) else {
return
}
for status in statuses {
guard self.getViewedStatus(accountId: accountId, statusId: status.id, modelContext: modelContext) == nil else {
continue
}
let viewedStatus = ViewedStatus(id: status.id, reblogId: status.reblog?.id, date: Date())
modelContext.insert(viewedStatus)
viewedStatus.pixelfedAccount = accountDataFromDb
accountDataFromDb.viewedStatuses.append(viewedStatus)
}
try modelContext.save()
}
/// Check if given status (real picture) has been already visible on the timeline (during last month).
func hasBeenAlreadyOnTimeline(accountId: String, status: Status, modelContext: ModelContext) -> Bool {
guard let reblog = status.reblog else {
return false
}
do {
let reblogId = reblog.id
let statusId = status.id
var fetchDescriptor = FetchDescriptor<ViewedStatus>(
// Here we are finding status which is older then checked status AND orginal status has been visible OR same reblogged by different user status has been visible.
predicate: #Predicate { $0.pixelfedAccount?.id == accountId && $0.id < statusId && ($0.id == reblogId || $0.reblogId == reblogId) }
)
fetchDescriptor.fetchLimit = 1
fetchDescriptor.includePendingChanges = true
guard try modelContext.fetch(fetchDescriptor).first != nil else {
return false
}
return true
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching viewed statuses (hasBeenAlreadyOnTimeline).")
return false
}
}
/// Mark to delete statuses older then one month.
func deleteOldViewedStatuses(modelContext: ModelContext) throws {
let oldViewedStatuses = self.getOldViewedStatuses(modelContext: modelContext)
for status in oldViewedStatuses {
modelContext.delete(status)
}
try modelContext.save()
}
private func getViewedStatus(accountId: String, statusId: String, modelContext: ModelContext) -> ViewedStatus? {
do {
var fetchDescriptor = FetchDescriptor<ViewedStatus>(
predicate: #Predicate { $0.id == statusId && $0.pixelfedAccount?.id == accountId }
)
fetchDescriptor.fetchLimit = 1
fetchDescriptor.includePendingChanges = true
return try modelContext.fetch(fetchDescriptor).first
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching viewed statuses (getOldViewedStatuses).")
return nil
}
}
private func getOldViewedStatuses(modelContext: ModelContext) -> [ViewedStatus] {
guard let date = Calendar.current.date(byAdding: .month, value: -1, to: Date()) else {
return []
}
do {
var fetchDescriptor = FetchDescriptor<ViewedStatus>(
predicate: #Predicate { $0.date < date }
)
fetchDescriptor.includePendingChanges = true
return try modelContext.fetch(fetchDescriptor)
} catch {
CoreDataError.shared.handle(error, message: "Error during fetching viewed statuses (getOldViewedStatuses).")
return []
}
}
}

View File

@ -1,14 +1,13 @@
// swift-tools-version: 5.8
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "EnvironmentKit",
defaultLocalization: "en",
platforms: [
.iOS(.v16),
.macOS(.v12),
.watchOS(.v8)
.iOS(.v17)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.

View File

@ -9,7 +9,7 @@ import SwiftUI
import PixelfedKit
import ClientKit
public class ApplicationState: ObservableObject {
@Observable public class ApplicationState {
public static let shared = ApplicationState()
private init() { }
@ -24,93 +24,110 @@ public class ApplicationState: ObservableObject {
private static let defaults = Defaults()
/// Actual signed in account.
@Published public private(set) var account: AccountModel?
public private(set) var account: AccountModel?
/// The maximum number of allowed characters per status.
@Published public private(set) var statusMaxCharacters = defaults.statusMaxCharacters
public private(set) var statusMaxCharacters = defaults.statusMaxCharacters
/// The maximum number of media attachments that can be added to a status.
@Published public private(set) var statusMaxMediaAttachments = defaults.statusMaxMediaAttachments
public private(set) var statusMaxMediaAttachments = defaults.statusMaxMediaAttachments
/// Each URL in a status will be assumed to be exactly this many characters.
@Published public private(set) var statusCharactersReservedPerUrl = defaults.statusCharactersReservedPerUrl
public private(set) var statusCharactersReservedPerUrl = defaults.statusCharactersReservedPerUrl
/// Last notification seen by the user.
public var lastSeenNotificationId: String?
/// Amount of new notifications.
public var amountOfNewNotifications = 0
/// Last status seen by the user.
@Published public var lastSeenStatusId: String?
public var lastSeenStatusId: String?
/// Amount of new statuses which are not displayed yet to the user.
@Published public var amountOfNewStatuses = 0
public var amountOfNewStatuses = 0
/// Model for newly created comment.
@Published public var newComment: CommentModel?
/// Id of latest published status by the user.
public var latestPublishedStatusId: String?
/// Active icon name.
@Published public var activeIcon = "Default"
public var activeIcon = "Default"
/// Tint color in whole application.
@Published public var tintColor = TintColor.accentColor2
public var tintColor = TintColor.accentColor2
/// Application theme.
@Published public var theme = Theme.system
public var theme = Theme.system
/// Avatar shape.
@Published public var avatarShape = AvatarShape.circle
public var avatarShape = AvatarShape.circle
/// Status id for showed interaction row.
@Published public var showInteractionStatusId = ""
public var showInteractionStatusId = ""
/// Should we fire haptic when user change tabs.
@Published public var hapticTabSelectionEnabled = true
public var hapticTabSelectionEnabled = true
/// Should we fire haptic when user refresh list.
@Published public var hapticRefreshEnabled = true
public var hapticRefreshEnabled = true
/// Should we fire haptic when user tap button.
@Published public var hapticButtonPressEnabled = true
public var hapticButtonPressEnabled = true
/// Should we fire haptic when animation is finished.
@Published public var hapticAnimationEnabled = true
public var hapticAnimationEnabled = true
/// Should we fire haptic when notification occures.
@Published public var hapticNotificationEnabled = true
public var hapticNotificationEnabled = true
/// Should sensitive photos without mask.
@Published public var showSensitive = false
public var showSensitive = false
/// Should photo description for visually impaired be displayed.
@Published public var showPhotoDescription = false
public var showPhotoDescription = false
/// Status which should be shown from URL.
@Published public var showStatusId: String?
public var showStatusId: String?
/// Account which should be shown from URL.
@Published public var showAccountId: String?
public var showAccountId: String?
/// Updated user profile.
@Published public var updatedProfile: Account?
public var updatedProfile: Account?
/// Information which menu should be shown (top or bottom).
@Published public var menuPosition = MenuPosition.top
public var menuPosition = MenuPosition.top
/// Should avatars be visible on timelines.
@Published public var showAvatarsOnTimeline = false
public var showAvatarsOnTimeline = false
/// Should favourites be visible on timelines.
@Published public var showFavouritesOnTimeline = false
public var showFavouritesOnTimeline = false
/// Should ALT icon be visible on timelines.
@Published public var showAltIconOnTimeline = false
public var showAltIconOnTimeline = false
/// Show warning about missing ALT texts on compose screen.
@Published public var warnAboutMissingAlt = true
public var warnAboutMissingAlt = true
/// Show grid of photos on user profile.
@Published public var showGridOnUserProfile = false
public var showGridOnUserProfile = false
public func changeApplicationState(accountModel: AccountModel, instance: Instance?, lastSeenStatusId: String?) {
/// Show reboosted statuses on home timeline.
public var showReboostedStatuses = false
/// Hide statuses without ALT text.
public var hideStatusesWithoutAlt = false
/// Should show application badge.
public var showApplicationBadge = false
public func changeApplicationState(accountModel: AccountModel, instance: Instance?, lastSeenStatusId: String?, lastSeenNotificationId: String?) {
self.account = accountModel
self.lastSeenNotificationId = lastSeenNotificationId
self.lastSeenStatusId = lastSeenStatusId
self.amountOfNewStatuses = 0
self.amountOfNewNotifications = 0
if let statusesConfiguration = instance?.configuration?.statuses {
self.statusMaxCharacters = statusesConfiguration.maxCharacters
@ -126,7 +143,9 @@ public class ApplicationState: ObservableObject {
public func clearApplicationState() {
self.account = nil
self.lastSeenStatusId = nil
self.lastSeenNotificationId = nil
self.amountOfNewStatuses = 0
self.amountOfNewNotifications = 0
self.statusMaxCharacters = ApplicationState.defaults.statusMaxCharacters
self.statusMaxMediaAttachments = ApplicationState.defaults.statusMaxMediaAttachments

View File

@ -0,0 +1,15 @@
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
// Licensed under the Apache License 2.0.
//
import OSLog
public extension Logger {
/// Using your bundle identifier is a great way to ensure a unique identifier.
private static var subsystem = Bundle.main.bundleIdentifier ?? "dev.mczachurski.vernissage"
/// Logs the main informations.
static let main = Logger(subsystem: subsystem, category: "main")
}

View File

@ -0,0 +1,5 @@
{
"sourceLanguage" : "en",
"strings" : {},
"version" : "1.0"
}

View File

@ -22,5 +22,6 @@ public struct AppConstants {
public static let accountUri = "\(AppConstants.accountScheme)://\(accountCallbackPart)"
public static let imagePipelineCacheName = "dev.mczachurski.Vernissage.DataCache"
public static let backgroundFetcherName = "dev.mczachurski.Vernissage.NotificationFetcher"
public static let coreDataPersistantContainerName = "Vernissage"
}

File diff suppressed because it is too large Load Diff

View File

@ -1,371 +0,0 @@
// MARK: Common strings.
"global.title.contentWarning" = "Sensitive content";
"global.title.seePost" = "See post";
"global.title.refresh" = "Refresh";
"global.title.momentsAgo" = "moments ago";
"global.title.success" = "Success";
"global.title.photoSaved" = "Photo has been saved.";
"global.title.ok" = "OK";
"global.title.showMore" = "Show more";
"global.title.showLess" = "Show less";
"global.title.close" = "Close";
"global.error.refreshingCredentialsTitle" = "Refreshing credentials error.";
"global.error.refreshingCredentialsSubtitle" = "Please sign in again to Pixelfed.";
// MARK: Global errors.
"global.error.unexpected" = "Unexpected error.";
"global.error.statusesNotRetrieved" = "Statuses not retrieved.";
"global.error.errorDuringDownloadStatuses" = "Error during download statuses from server.";
"global.error.errorDuringDownloadHashtag" = "Error during download tag from server.";
"global.error.hashtagNotExists" = "Hashtag does not exists.";
"global.error.errorDuringImageDownload" = "Cannot download image.";
"global.error.canceledImageDownload" = "Download image has been canceled.";
"global.error.errorDuringDataLoad" = "Loading data failed.";
"global.error.errorDuringUserRead" = "Cannot retrieve user account.";
"global.error.badUrlServer" = "Bad url to server.";
"global.error.accessTokenNotFound" = "Access token not found.";
"global.error.errorDuringDownloadStatus" = "Error during download status from server.";
"global.error.errorDuringPurchaseVerification" = "Purchase verification failed.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Home";
"mainview.tab.localTimeline" = "Local";
"mainview.tab.federatedTimeline" = "Federated";
"mainview.tab.trendingPhotos" = "Photos";
"mainview.tab.trendingTags" = "Tags";
"mainview.tab.trendingAccounts" = "Accounts";
"mainview.tab.userProfile" = "Profile";
"mainview.tab.notifications" = "Notifications";
"mainview.tab.search" = "Search";
"mainview.tab.trending" = "Trending";
// MARK: Main view (leading navigation bar).
"mainview.menu.settings" = "Settings";
// MARK: Main view (error notifications).
"mainview.error.switchAccounts" = "Cannot switch accounts.";
// MARK: Home timeline.
"home.title.allCaughtUp" = "You're all caught up";
"home.title.noPhotos" = "Unfortunately, there are no photos here.";
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
"statuses.navigationBar.localTimeline" = "Local";
"statuses.navigationBar.federatedTimeline" = "Federated";
"statuses.navigationBar.favourites" = "Favourites";
"statuses.navigationBar.bookmarks" = "Bookmarks";
"statuses.title.noPhotos" = "Unfortunately, there are no photos here.";
"statuses.title.tagFollowed" = "You are following the tag.";
"statuses.title.tagUnfollowed" = "Tag has been unfollowed.";
"statuses.error.loadingStatusesFailed" = "Loading statuses failed.";
"statuses.error.tagFollowFailed" = "Follow tag failed.";
"statuses.error.tagUnfollowFailed" = "Unfollow tag failed.";
// Mark: Search view.
"search.navigationBar.title" = "Search";
"search.title.placeholder" = "Search...";
"search.title.usersWith" = "Users with %@";
"search.title.goToUser" = "Go to user %@";
"search.title.hashtagWith" = "Hashtags with %@";
"search.title.goToHashtag" = "Go to hashtag %@";
// Mark: Trending statuses.
"trendingStatuses.navigationBar.title" = "Photos";
"trendingStatuses.title.daily" = "Daily";
"trendingStatuses.title.monthly" = "Monthly";
"trendingStatuses.title.yearly" = "Yearly";
"trendingStatuses.error.loadingStatusesFailed" = "Loading statuses failed.";
"trendingStatuses.title.noPhotos" = "Unfortunately, there are no photos here.";
// Mark: Trending tags.
"trendingTags.navigationBar.title" = "Tags";
"trendingTags.title.noTags" = "Unfortunately, there are no tags here.";
"trendingTags.title.amountOfPosts" = "%d posts";
"trendingTags.error.loadingTagsFailed" = "Loading tags failed.";
// Mark: Trending accounts.
"trendingAccounts.navigationBar.title" = "Accounts";
"trendingAccounts.title.noAccounts" = "Unfortunately, there is no one here.";
"trendingAccounts.error.loadingAccountsFailed" = "Loading accounts failed.";
// Mark: User profile view.
"userProfile.title.openInBrowser" = "Open in browser";
"userProfile.title.share" = "Share";
"userProfile.title.unmute" = "Unmute";
"userProfile.title.mute" = "Mute";
"userProfile.title.unblock" = "Unblock";
"userProfile.title.block" = "Block";
"userProfile.title.favourites" = "Favourites";
"userProfile.title.bookmarks" = "Bookmarks";
"userProfile.title.posts" = "Posts";
"userProfile.title.followers" = "Followers";
"userProfile.title.following" = "Following";
"userProfile.title.joined" = "Joined %@";
"userProfile.title.unfollow" = "Unfollow";
"userProfile.title.follow" = "Follow";
"userProfile.title.instance" = "Instance information";
"userProfile.title.blocks" = "Blocked accounts";
"userProfile.title.mutes" = "Muted accounts";
"userProfile.title.muted" = "Account muted";
"userProfile.title.unmuted" = "Account unmuted";
"userProfile.title.blocked" = "Account blocked";
"userProfile.title.unblocked" = "Account unblocked";
"userProfile.title.report" = "Report";
"userProfile.title.followsYou" = "Follows you";
"userProfile.title.requestFollow" = "Request follow";
"userProfile.title.cancelRequestFollow" = "Cancel request";
"userProfile.title.followRequests" = "Follow requests";
"userProfile.title.privateProfileTitle" = "This profile is private.";
"userProfile.title.privateProfileSubtitle" = "Only approved followers can see photos.";
"userProfile.error.notExists" = "Account does not exists.";
"userProfile.error.loadingAccountFailed" = "Error during download account from server.";
"userProfile.error.muting" = "Muting/unmuting action failed.";
"userProfile.error.block" = "Block/unblock action failed.";
"userProfile.error.relationship" = "Relationship action failed.";
"userProfile.title.edit" = "Edit";
"userProfile.title.muted" = "Muted";
"userProfile.title.blocked" = "Blocked";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Notifications";
"notifications.title.noNotifications" = "Unfortunately, there is nothing here.";
"notifications.title.followedYou" = "followed you";
"notifications.title.mentionedYou" = "mentioned you";
"notifications.title.boosted" = "boosted";
"notifications.title.favourited" = "favourited";
"notifications.title.postedStatus" = "posted status";
"notifications.title.followRequest" = "follow request";
"notifications.title.poll" = "poll";
"notifications.title.updatedStatus" = "updated status";
"notifications.title.signedUp" = "signed up";
"notifications.title.newReport" = "new report";
"notifications.error.loadingNotificationsFailed" = "Loading notifications failed.";
// Mark: Compose view.
"compose.navigationBar.title" = "Compose";
"compose.title.everyone" = "Everyone";
"compose.title.unlisted" = "Unlisted";
"compose.title.followers" = "Followers";
"compose.title.attachPhotoFull" = "Attach a photo and type what's on your mind";
"compose.title.attachPhotoMini" = "Type what's on your mind";
"compose.title.publish" = "Publish";
"compose.title.cancel" = "Cancel";
"compose.title.writeContentWarning" = "Write content warning";
"compose.title.commentsWillBeDisabled" = "Comments will be disabled";
"compose.title.statusPublished" = "Status published";
"compose.title.tryToUpload" = "Try to upload";
"compose.title.delete" = "Delete";
"compose.title.edit" = "Edit";
"compose.title.photos" = "Photos library";
"compose.title.camera" = "Take photo";
"compose.title.files" = "Browse files";
"compose.title.missingAltTexts" = "Missing ALT texts";
"compose.title.missingAltTextsWarning" = "Not all images have been described for the visually impaired. Would you like to send photos anyway?";
"compose.error.loadingPhotosFailed" = "Cannot retreive image from library.";
"compose.error.postingPhotoFailed" = "Error during posting photo.";
"compose.error.postingStatusFailed" = "Error during posting status.";
// Mark: Photo editor view.
"photoEdit.navigationBar.title" = "Photo details";
"photoEdit.title.photo" = "Photo";
"photoEdit.title.accessibility" = "Accessibility";
"photoEdit.title.accessibilityDescription" = "Description for the visually impaired";
"photoEdit.title.save" = "Save";
"photoEdit.title.cancel" = "Cancel";
"photoEdit.error.updatePhotoFailed" = "Error during updating photo.";
// Mark: Place selector view.
"placeSelector.navigationBar.title" = "Places";
"placeSelector.title.search" = "Search...";
"placeSelector.title.buttonSearch" = "Search";
"placeSelector.title.cancel" = "Cancel";
"placeSelector.error.loadingPlacesFailed" = "Loading notifications failed.";
// Mark: Settings view.
"settings.navigationBar.title" = "Settings";
"settings.title.close" = "Close";
"settings.title.version" = "Version";
"settings.title.accounts" = "Accounts";
"settings.title.newAccount" = "New account";
"settings.title.accent" = "Accent";
"settings.title.theme" = "Theme";
"settings.title.system" = "System";
"settings.title.light" = "Light";
"settings.title.dark" = "Dark";
"settings.title.avatar" = "Avatar";
"settings.title.circle" = "Circle";
"settings.title.rounderRectangle" = "Rounded rectangle";
"settings.title.other" = "Other";
"settings.title.thirdParty" = "Third party";
"settings.title.reportBug" = "Report a bug";
"settings.title.githubIssues" = "Issues on Github";
"settings.title.follow" = "Follow me";
"settings.title.support" = "Support";
"settings.title.thankYouTitle" = "Thank you 💕";
"settings.title.thankYouMessage" = "Thanks for your purchase. Purchases both big and small help us keep our dream of providing the best quality products to our customers. We hope youre loving Vernissage.";
"settings.title.thankYouClose" = "Close";
"settings.title.haptics" = "Haptics";
"settings.title.hapticsTabSelection" = "Tab selection";
"settings.title.hapticsButtonPress" = "Button press";
"settings.title.hapticsListRefresh" = "List refresh";
"settings.title.hapticsAnimationFinished" = "Animation finished";
"settings.title.mediaSettings" = "Media settings";
"settings.title.alwaysShowSensitiveTitle" = "Always show NSFW";
"settings.title.alwaysShowSensitiveDescription" = "Force show all NFSW (sensitive) media without warnings";
"settings.title.alwaysShowAltTitle" = "Show alternative text";
"settings.title.alwaysShowAltDescription" = "Show alternative text if present on status details screen";
"settings.title.general" = "General";
"settings.title.applicationIcon" = "Application icon";
"settings.title.followVernissage" = "Follow Vernissage";
"settings.title.mastodonAccount" = "Mastodon account";
"settings.title.pixelfedAccount" = "Pixelfed account";
"settings.title.openPage" = "Open";
"settings.title.privacyPolicy" = "Privacy policy";
"settings.title.terms" = "Terms & Conditions";
"settings.title.sourceCode" = "Source code";
"settings.title.rate" = "Rate Vernissage";
"settings.title.socials" = "Socials";
"settings.title.menuPosition" = "Menu position";
"settings.title.topMenu" = "Navigation bar";
"settings.title.bottomRightMenu" = "Bottom right";
"settings.title.bottomLeftMenu" = "Bottom left";
"settings.title.showAvatars" = "Show avatars";
"settings.title.showAvatarsOnTimeline" = "Avatars will be displayed on timelines";
"settings.title.showFavourite" = "Show favourites";
"settings.title.showFavouriteOnTimeline" = "Favourites will be displayed on timelines";
"settings.title.showAltText" = "Show ALT icon";
"settings.title.showAltTextOnTimeline" = "ALT icon will be displayed on timelines";
"settings.title.warnAboutMissingAltTitle" = "Warn of missing ALT text";
"settings.title.warnAboutMissingAltDescription" = "A warning about missing ALT texts will be displayed before publishing new post.";
// Mark: Signin view.
"signin.navigationBar.title" = "Sign in to Pixelfed";
"signin.title.serverAddress" = "Server address";
"signin.title.signIn" = "Sign in";
"signin.title.enterServerAddress" = "Enter server address";
"signin.title.howToJoinLink" = "How to join Pixelfed";
"signin.title.chooseServer" = "Or choose Pixelfed server";
"signin.title.amountOfUsers" = "%d users";
"signin.title.amountOStatuses" = "%d statuses";
"signin.error.communicationFailed" = "Communication with server failed.";
// Mark: Status view.
"status.navigationBar.title" = "Details";
"status.title.uploaded" = "Uploaded";
"status.title.via" = "via %@";
"status.title.reboostedBy" = "Boosted by";
"status.title.favouritedBy" = "Favourited by";
"status.title.openInBrowser" = "Open in browser";
"status.title.shareStatus" = "Share status";
"status.title.yourStatus" = "Your status";
"status.title.delete" = "Delete";
"status.title.reboosted" = "Boosted";
"status.title.unreboosted" = "Unboosted";
"status.title.favourited" = "Favourited";
"status.title.unfavourited" = "Unfavourited";
"status.title.bookmarked" = "Bookmarked";
"status.title.unbookmarked" = "Unbookmarked";
"status.title.statusDeleted" = "Status deleted";
"status.title.reboost" = "Boost";
"status.title.unreboost" = "Unboost";
"status.title.favourite" = "Favourite";
"status.title.unfavourite" = "Unfavourite";
"status.title.bookmark" = "Bookmark";
"status.title.unbookmark" = "Unbookmark";
"status.title.comment" = "Comment";
"status.title.report" = "Report";
"status.title.saveImage" = "Save image";
"status.title.showMediaDescription" = "Show media description";
"status.title.mediaDescription" = "Media description";
"status.title.shareImage" = "Share image";
"status.title.altText" = "ALT";
"status.error.loadingStatusFailed" = "Loading status failed.";
"status.error.notFound" = "Status not existing anymore.";
"status.error.loadingCommentsFailed" = "Comments cannot be downloaded.";
"status.error.reboostFailed" = "Boost action failed.";
"status.error.favouriteFailed" = "Favourite action failed.";
"status.error.bookmarkFailed" = "Bookmark action failed.";
"status.error.deleteFailed" = "Delete action failed.";
// Mark: Accounts view.
"accounts.navigationBar.followers" = "Followers";
"accounts.navigationBar.following" = "Following";
"accounts.navigationBar.favouritedBy" = "Favourited by";
"accounts.navigationBar.reboostedBy" = "Boosted by";
"accounts.navigationBar.blocked" = "Blocked accounts";
"accounts.navigationBar.mutes" = "Muted accounts";
"accounts.title.noAccounts" = "Unfortunately, there is no one here.";
"accounts.error.loadingAccountsFailed" = "Loading accounts failed.";
// Mark: Third party view.
"thirdParty.navigationBar.title" = "Third party";
// Mark: Widget view.
"widget.title.photoDescription" = "Widget with photos from Pixelfed.";
"widget.title.qrCodeDescription" = "Widget with QR Code to your Pixelfed profile.";
// Mark: In-app purchases.
"purchase.donut.title" = "Donut";
"purchase.donut.description" = "Treat me to a doughnut.";
"purchase.coffee.title" = "Coffee";
"purchase.coffee.description" = "Treat me to a coffee.";
"purchase.cake.title" = "Coffee & cake";
"purchase.cake.description" = "Treat me to a coffee and cake.";
// Mark: Edit profile.
"editProfile.navigationBar.title" = "Edit profile";
"editProfile.title.displayName" = "Display name";
"editProfile.title.bio" = "Bio";
"editProfile.title.website" = "Website";
"editProfile.title.save" = "Save";
"editProfile.title.accountSaved" = "Profile has been updated.";
"editProfile.title.photoInfo" = "The changed photo will be visible in the app and on the website with a small delay.";
"editProfile.title.privateAccount" = "Private account";
"editProfile.title.privateAccountInfo" = "When your account is private, only people you approve can see your photos and videos on Pixelfed. Your existing followers won't be affected.";
"editProfile.error.saveAccountFailed" = "Saving profile failed.";
"editProfile.error.loadingAvatarFailed" = "Loading avatar failed.";
"editProfile.error.noProfileData" = "Profile data cannot be displayed.";
"editProfile.error.loadingAccountFailed" = "Error during download account from server.";
// Mark: Instance information.
"instance.navigationBar.title" = "Instance";
"instance.title.instanceInfo" = "Instance info";
"instance.title.name" = "Name";
"instance.title.address" = "Address";
"instance.title.email" = "Email";
"instance.title.version" = "Version";
"instance.title.users" = "Users";
"instance.title.posts" = "Posts";
"instance.title.domains" = "Domains";
"instance.title.registrations" = "Registrations";
"instance.title.approvalRequired" = "Approval required";
"instance.title.rules" = "Instance rules";
"instance.title.contact" = "Contact";
"instance.title.pixelfedAccount" = "Pixelfed account";
"instance.error.noInstanceData" = "Instance data cannot be displayed.";
"instance.error.loadingDataFailed" = "Error during download instance data from server.";
// Mark: Report screen.
"report.navigationBar.title" = "Report";
"report.title.close" = "Close";
"report.title.send" = "Send";
"report.title.userReported" = "User has been reported";
"report.title.postReported" = "Post has been reported";
"report.title.reportType" = "Type of abuse";
"report.title.spam" = "It's a spam";
"report.title.sensitive" = "Nudity or sexual activity";
"report.title.abusive" = "Hate speech or symbols";
"report.title.underage" = "Underage account";
"report.title.violence" = "Violence or dangerous organisations";
"report.title.copyright" = "Copyright infringement";
"report.title.impersonation" = "Impersonation";
"report.title.scam" = "Bullying or harassment";
"report.title.terrorism" = "Terrorism";
"report.error.notReported" = "Error during sending report.";
// Mark: Following requests.
"followingRequests.navigationBar.title" = "Following requests";
"followingRequests.title.approve" = "Approve";
"followingRequests.title.reject" = "Reject";
"followingRequests.error.approve" = "Error during approving request.";
"followingRequests.error.reject" = "Error during rejecting request.";

View File

@ -1,371 +0,0 @@
// MARK: Common strings.
"global.title.contentWarning" = "Contenido sensible";
"global.title.seePost" = "Ver publicación";
"global.title.refresh" = "Actualizar";
"global.title.momentsAgo" = "hace uno momento";
"global.title.success" = "Éxito";
"global.title.photoSaved" = "La foto se ha guardado.";
"global.title.ok" = "Aceptar";
"global.title.showMore" = "Mostrar más";
"global.title.showLess" = "Mostrar menos";
"global.title.close" = "Cerrar";
"global.error.refreshingCredentialsTitle" = "Error al actualizar las credenciales.";
"global.error.refreshingCredentialsSubtitle" = "Por favor, vuelve a iniciar sesión en Pixelfed.";
// MARK: Global errors.
"global.error.unexpected" = "Error inesperado.";
"global.error.statusesNotRetrieved" = "No se pudieron obtener los estados.";
"global.error.errorDuringDownloadStatuses" = "Error durante la descarga de estados del servidor.";
"global.error.errorDuringDownloadHashtag" = "Error durante la descarga de etiquetas del servidor.";
"global.error.hashtagNotExists" = "La etiqueta no existe.";
"global.error.errorDuringImageDownload" = "No se puede descargar la imagen.";
"global.error.canceledImageDownload" = "La descarga de la imagen ha sido cancelada.";
"global.error.errorDuringDataLoad" = "Error al cargar los datos.";
"global.error.errorDuringUserRead" = "No se puede recuperar la cuenta de usuario.";
"global.error.badUrlServer" = "URL incorrecta del servidor.";
"global.error.accessTokenNotFound" = "Token de acceso no encontrado.";
"global.error.errorDuringDownloadStatus" = "Error durante la descarga del estado del servidor.";
"global.error.errorDuringPurchaseVerification" = "Fallo en la verificación de la compra.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Inicio";
"mainview.tab.localTimeline" = "Local";
"mainview.tab.federatedTimeline" = "Federado";
"mainview.tab.trendingPhotos" = "Fotos";
"mainview.tab.trendingTags" = "Etiquetas";
"mainview.tab.trendingAccounts" = "Cuentas";
"mainview.tab.userProfile" = "Perfil";
"mainview.tab.notifications" = "Notificaciones";
"mainview.tab.search" = "Buscar";
"mainview.tab.trending" = "Tendencias";
// MARK: Main view (leading navigation bar).
"mainview.menu.settings" = "Ajustes";
// MARK: Main view (error notifications).
"mainview.error.switchAccounts" = "No se pueden cambiar las cuentas.";
// MARK: Home timeline.
"home.title.allCaughtUp" = "Estás al día";
"home.title.noPhotos" = "Desafortunadamente, no hay fotos aquí.";
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
"statuses.navigationBar.localTimeline" = "Local";
"statuses.navigationBar.federatedTimeline" = "Federado";
"statuses.navigationBar.favourites" = "Favoritos";
"statuses.navigationBar.bookmarks" = "Marcadores";
"statuses.title.noPhotos" = "Desafortunadamente, no hay fotos aquí.";
"statuses.title.tagFollowed" = "Estás siguiendo la etiqueta.";
"statuses.title.tagUnfollowed" = "Se ha dejado de seguir la etiqueta.";
"statuses.error.loadingStatusesFailed" = "Error al cargar los estados.";
"statuses.error.tagFollowFailed" = "Error al seguir la etiqueta.";
"statuses.error.tagUnfollowFailed" = "Error al dejar de seguir la etiqueta.";
// Mark: Search view.
"search.navigationBar.title" = "Buscar";
"search.title.placeholder" = "Buscar...";
"search.title.usersWith" = "Usuarios con %@";
"search.title.goToUser" = "Ir al usuario %@";
"search.title.hashtagWith" = "Etiquetas con %@";
"search.title.goToHashtag" = "Ir a la etiqueta %@";
// Mark: Trending statuses.
"trendingStatuses.navigationBar.title" = "Fotos";
"trendingStatuses.title.daily" = "Diario";
"trendingStatuses.title.monthly" = "Mensual";
"trendingStatuses.title.yearly" = "Anual";
"trendingStatuses.error.loadingStatusesFailed" = "Error al cargar los estados.";
"trendingStatuses.title.noPhotos" = "Desafortunadamente, no hay fotos aquí.";
// Mark: Trending tags.
"trendingTags.navigationBar.title" = "Etiquetas";
"trendingTags.title.noTags" = "Desafortunadamente, no hay etiquetas aquí.";
"trendingTags.title.amountOfPosts" = "%d publicaciones";
"trendingTags.error.loadingTagsFailed" = "Error al cargar las etiquetas.";
// Mark: Trending accounts.
"trendingAccounts.navigationBar.title" = "Cuentas";
"trendingAccounts.title.noAccounts" = "Desafortunadamente, aquí no hay nadie.";
"trendingAccounts.error.loadingAccountsFailed" = "Error al cargar las cuentas.";
// Mark: User profile view.
"userProfile.title.openInBrowser" = "Abrir en el navegador";
"userProfile.title.share" = "Compartir";
"userProfile.title.unmute" = "Quitar silencio";
"userProfile.title.mute" = "Silenciar";
"userProfile.title.unblock" = "Desbloquear";
"userProfile.title.block" = "Bloquear";
"userProfile.title.favourites" = "Favoritos";
"userProfile.title.bookmarks" = "Marcadores";
"userProfile.title.posts" = "Publicaciones";
"userProfile.title.followers" = "Seguidores";
"userProfile.title.following" = "Siguiendo";
"userProfile.title.joined" = "Unido a %@";
"userProfile.title.unfollow" = "Dejar de seguir";
"userProfile.title.follow" = "Seguir";
"userProfile.title.instance" = "Información de la instancia";
"userProfile.title.blocks" = "Cuentas bloqueadas";
"userProfile.title.mutes" = "Cuentas silenciadas";
"userProfile.title.muted" = "Cuenta silenciada";
"userProfile.title.unmuted" = "Cuenta sin silencio";
"userProfile.title.blocked" = "Cuenta bloqueada";
"userProfile.title.unblocked" = "Cuenta desbloqueada";
"userProfile.title.report" = "Informar";
"userProfile.title.followsYou" = "Te sigue";
"userProfile.title.requestFollow" = "Solicitar seguir";
"userProfile.title.cancelRequestFollow" = "Cancelar solicitud";
"userProfile.title.followRequests" = "Solicitudes de seguimiento";
"userProfile.title.privateProfileTitle" = "Este perfil es privado.";
"userProfile.title.privateProfileSubtitle" = "Solo los seguidores aprobados pueden ver las fotos.";
"userProfile.error.notExists" = "La cuenta no existe.";
"userProfile.error.loadingAccountFailed" = "Error al descargar la cuenta del servidor.";
"userProfile.error.muting" = "Error al silenciar/quitar silencio.";
"userProfile.error.block" = "Error al bloquear/desbloquear.";
"userProfile.error.relationship" = "Error en la acción de relación.";
"userProfile.title.edit" = "Editar";
"userProfile.title.muted" = "Silenciado";
"userProfile.title.blocked" = "Bloqueado";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Notificaciones";
"notifications.title.noNotifications" = "Desafortunadamente, aquí no hay nada.";
"notifications.title.followedYou" = "te ha seguido";
"notifications.title.mentionedYou" = "te ha mencionado";
"notifications.title.boosted" = "ha compartido";
"notifications.title.favourited" = "le ha gustado";
"notifications.title.postedStatus" = "ha publicado un estado";
"notifications.title.followRequest" = "solicitud de seguimiento";
"notifications.title.poll" = "encuesta";
"notifications.title.updatedStatus" = "estado actualizado";
"notifications.title.signedUp" = "se ha registrado";
"notifications.title.newReport" = "nuevo informe";
"notifications.error.loadingNotificationsFailed" = "Error al cargar las notificaciones.";
// Mark: Compose view.
"compose.navigationBar.title" = "Componer";
"compose.title.everyone" = "Todos";
"compose.title.unlisted" = "No listado";
"compose.title.followers" = "Seguidores";
"compose.title.attachPhotoFull" = "Adjunta una foto y escribe lo que piensas";
"compose.title.attachPhotoMini" = "Escribe lo que piensas";
"compose.title.publish" = "Publicar";
"compose.title.cancel" = "Cancelar";
"compose.title.writeContentWarning" = "Escribir aviso de contenido";
"compose.title.commentsWillBeDisabled" = "Los comentarios estarán desactivados";
"compose.title.statusPublished" = "Estado publicado";
"compose.title.tryToUpload" = "Intentar subir";
"compose.title.delete" = "Eliminar";
"compose.title.edit" = "Editar";
"compose.title.photos" = "Fototeca";
"compose.title.camera" = "Hacer una foto";
"compose.title.files" = "Explorar archivos";
"compose.title.missingAltTexts" = "Textos ALT faltantes";
"compose.title.missingAltTextsWarning" = "No todas las imágenes han sido descritas para personas con discapacidad visual. ¿Te gustaría enviar las fotos de todos modos?";
"compose.error.loadingPhotosFailed" = "No se puede recuperar la imagen de la biblioteca.";
"compose.error.postingPhotoFailed" = "Error al publicar la foto.";
"compose.error.postingStatusFailed" = "Error al publicar el estado.";
// Mark: Photo editor view.
"photoEdit.navigationBar.title" = "Detalles de la foto";
"photoEdit.title.photo" = "Foto";
"photoEdit.title.accessibility" = "Accesibilidad";
"photoEdit.title.accessibilityDescription" = "Descripción para personas con discapacidad visual";
"photoEdit.title.save" = "Guardar";
"photoEdit.title.cancel" = "Cancelar";
"photoEdit.error.updatePhotoFailed" = "Error al actualizar la foto.";
// Mark: Place selector view.
"placeSelector.navigationBar.title" = "Lugares";
"placeSelector.title.search" = "Buscar...";
"placeSelector.title.buttonSearch" = "Buscar";
"placeSelector.title.cancel" = "Cancelar";
"placeSelector.error.loadingPlacesFailed" = "Error al cargar las notificaciones.";
// Mark: Settings view.
"settings.navigationBar.title" = "Ajustes";
"settings.title.close" = "Cerrar";
"settings.title.version" = "Versión";
"settings.title.accounts" = "Cuentas";
"settings.title.newAccount" = "Nueva cuenta";
"settings.title.accent" = "Acento";
"settings.title.theme" = "Tema";
"settings.title.system" = "Sistema";
"settings.title.light" = "Claro";
"settings.title.dark" = "Oscuro";
"settings.title.avatar" = "Avatar";
"settings.title.circle" = "Círculo";
"settings.title.rounderRectangle" = "Rectángulo redondeado";
"settings.title.other" = "Otros";
"settings.title.thirdParty" = "Terceros";
"settings.title.reportBug" = "Informar de un error";
"settings.title.githubIssues" = "Problemas en Github";
"settings.title.follow" = "Sígueme";
"settings.title.support" = "Soporte";
"settings.title.thankYouTitle" = "Gracias 💕";
"settings.title.thankYouMessage" = "Gracias por tu compra. Tanto las compras grandes como las pequeñas nos ayudan a mantener nuestro sueño de proporcionar productos de la mejor calidad a nuestros clientes. Esperamos que estés disfrutando de Vernissage.";
"settings.title.thankYouClose" = "Cerrar";
"settings.title.haptics" = "Respuesta háptica";
"settings.title.hapticsTabSelection" = "Selección de pestaña";
"settings.title.hapticsButtonPress" = "Pulsación de botón";
"settings.title.hapticsListRefresh" = "Actualizar lista";
"settings.title.hapticsAnimationFinished" = "Animación finalizada";
"settings.title.mediaSettings" = "Ajustes multimedia";
"settings.title.alwaysShowSensitiveTitle" = "Mostrar siempre NSFW";
"settings.title.alwaysShowSensitiveDescription" = "Mostrar siempre todos los medios NSFW (sensibles) sin advertencias";
"settings.title.alwaysShowAltTitle" = "Mostrar texto alternativo";
"settings.title.alwaysShowAltDescription" = "Mostrar el texto alternativo si está presente en la pantalla de detalles del estado";
"settings.title.general" = "General";
"settings.title.applicationIcon" = "Icono de la aplicación";
"settings.title.followVernissage" = "Sígueme en Vernissage";
"settings.title.mastodonAccount" = "Cuenta de Mastodon";
"settings.title.pixelfedAccount" = "Cuenta de Pixelfed";
"settings.title.openPage" = "Abrir";
"settings.title.privacyPolicy" = "Política de privacidad";
"settings.title.terms" = "Términos y condiciones";
"settings.title.sourceCode" = "Código fuente";
"settings.title.rate" = "Puntúa Vernissage";
"settings.title.socials" = "Redes sociales";
"settings.title.menuPosition" = "Posición del menú";
"settings.title.topMenu" = "Barra de navegación";
"settings.title.bottomRightMenu" = "Abajo a la derecha";
"settings.title.bottomLeftMenu" = "Abajo a la izquierda";
"settings.title.showAvatars" = "Mostrar avatares";
"settings.title.showAvatarsOnTimeline" = "Los avatares se mostrarán en las cronologías";
"settings.title.showFavourite" = "Mostrar favoritos";
"settings.title.showFavouriteOnTimeline" = "Los favoritos se mostrarán en las cronologías";
"settings.title.showAltText" = "Mostrar icono ALT";
"settings.title.showAltTextOnTimeline" = "El icono ALT se mostrará en las cronologíasS";
"settings.title.warnAboutMissingAltTitle" = "Advertir sobre el texto ALT faltante";
"settings.title.warnAboutMissingAltDescription" = "Se mostrará una advertencia sobre los textos ALT faltantes antes de publicar una nueva entrada.";
// Mark: Signin view.
"signin.navigationBar.title" = "Iniciar sesión en Pixelfed";
"signin.title.serverAddress" = "Dirección del servidor";
"signin.title.signIn" = "Iniciar sesión";
"signin.title.enterServerAddress" = "Introducir la dirección del servidor";
"signin.title.howToJoinLink" = "Cómo unirse a Pixelfed";
"signin.title.chooseServer" = "O elige un servidor Pixelfed";
"signin.title.amountOfUsers" = "%d usuarios";
"signin.title.amountOStatuses" = "%d estados";
"signin.error.communicationFailed" = "Error de comunicación con el servidor.";
// Mark: Status view.
"status.navigationBar.title" = "Detalles";
"status.title.uploaded" = "Subido";
"status.title.via" = "a través de %@";
"status.title.reboostedBy" = "Compartido por";
"status.title.favouritedBy" = "Le ha gustado a";
"status.title.openInBrowser" = "Abrir en el navegador";
"status.title.shareStatus" = "Compartir estado";
"status.title.yourStatus" = "Tu estado";
"status.title.delete" = "Eliminar";
"status.title.reboosted" = "Compartido";
"status.title.unreboosted" = "No compartido";
"status.title.favourited" = "Le ha gustado";
"status.title.unfavourited" = "No le ha gustado";
"status.title.bookmarked" = "Marcado";
"status.title.unbookmarked" = "No marcado";
"status.title.statusDeleted" = "Estado eliminado";
"status.title.reboost" = "Compartir";
"status.title.unreboost" = "No compartir";
"status.title.favourite" = "Me gusta";
"status.title.unfavourite" = "No me gusta";
"status.title.bookmark" = "Marcar";
"status.title.unbookmark" = "Desmarcar";
"status.title.comment" = "Comentario";
"status.title.report" = "Informar";
"status.title.saveImage" = "Guardar imagen";
"status.title.showMediaDescription" = "Mostrar descripción de medios";
"status.title.mediaDescription" = "Descripción de medios";
"status.title.shareImage" = "Compartir imagen";
"status.title.altText" = "ALT";
"status.error.loadingStatusFailed" = "Error al cargar el estado.";
"status.error.notFound" = "El estado ya no existe.";
"status.error.loadingCommentsFailed" = "No se pueden cargar los comentarios.";
"status.error.reboostFailed" = "Error al compartir.";
"status.error.favouriteFailed" = "Error al dar me gusta.";
"status.error.bookmarkFailed" = "Error al marcar.";
"status.error.deleteFailed" = "Error al eliminar.";
// Mark: Accounts view.
"accounts.navigationBar.followers" = "Seguidores";
"accounts.navigationBar.following" = "Siguiendo";
"accounts.navigationBar.favouritedBy" = "Le ha gustado a";
"accounts.navigationBar.reboostedBy" = "Compartido por";
"accounts.navigationBar.blocked" = "Cuentas bloqueadas";
"accounts.navigationBar.mutes" = "Cuentas silenciadas";
"accounts.title.noAccounts" = "Desafortunadamente, aquí no hay nadie.";
"accounts.error.loadingAccountsFailed" = "Error al cargar las cuentas.";
// Mark: Third party view.
"thirdParty.navigationBar.title" = "Terceros";
// Mark: Widget view.
"widget.title.photoDescription" = "Widget con fotos de Pixelfed.";
"widget.title.qrCodeDescription" = "Widget con el código QR de tu perfil de Pixelfed.";
// Mark: In-app purchases.
"purchase.donut.title" = "Rosquilla";
"purchase.donut.description" = "Dame una rosquilla.";
"purchase.coffee.title" = "Café";
"purchase.coffee.description" = "Dame un café.";
"purchase.cake.title" = "Café y pastel";
"purchase.cake.description" = "Dame un café y un pastel.";
// Mark: Edit profile.
"editProfile.navigationBar.title" = "Editar perfil";
"editProfile.title.displayName" = "Nombre para mostrar";
"editProfile.title.bio" = "Biografía";
"editProfile.title.website" = "Sitio web";
"editProfile.title.save" = "Guardar";
"editProfile.title.accountSaved" = "Perfil actualizado.";
"editProfile.title.photoInfo" = "La foto cambiada se mostrará en la aplicación y en el sitio web con un pequeño retraso.";
"editProfile.title.privateAccount" = "Cuenta privada";
"editProfile.title.privateAccountInfo" = "Cuando tu cuenta es privada, sólo las personas a las que apruebas pueden ver tus fotos y vídeos en Pixelfed. Tus seguidores existentes no se verán afectados.";
"editProfile.error.saveAccountFailed" = "Error al guardar el perfil.";
"editProfile.error.loadingAvatarFailed" = "Error al cargar el avatar.";
"editProfile.error.noProfileData" = "No se pueden mostrar los datos del perfil.";
"editProfile.error.loadingAccountFailed" = "Error al cargar los datos de la cuenta desde el servidor.";
// Mark: Instance information.
"instance.navigationBar.title" = "Instancia";
"instance.title.instanceInfo" = "Información de la instancia";
"instance.title.name" = "Nombre";
"instance.title.address" = "Dirección";
"instance.title.email" = "Correo electrónico";
"instance.title.version" = "Versión";
"instance.title.users" = "Usuarios";
"instance.title.posts" = "Publicaciones";
"instance.title.domains" = "Dominios";
"instance.title.registrations" = "Registros";
"instance.title.approvalRequired" = "Se requiere aprobación";
"instance.title.rules" = "Reglas de la instancia";
"instance.title.contact" = "Contacto";
"instance.title.pixelfedAccount" = "Cuenta de Pixelfed";
"instance.error.noInstanceData" = "No se pueden mostrar los datos de la instancia.";
"instance.error.loadingDataFailed" = "Error al cargar los datos de la instancia desde el servidor.";
// Mark: Report screen.
"report.navigationBar.title" = "Informe";
"report.title.close" = "Cerrar";
"report.title.send" = "Enviar";
"report.title.userReported" = "El usuario ha sido denunciado";
"report.title.postReported" = "La publicación ha sido denunciada";
"report.title.reportType" = "Tipo de abuso";
"report.title.spam" = "No deseado (spam)";
"report.title.sensitive" = "Desnudos o actividad sexual";
"report.title.abusive" = "Discurso o símbolos de odio";
"report.title.underage" = "Cuenta de menor de edad";
"report.title.violence" = "Violencia u organizaciones peligrosas";
"report.title.copyright" = "Infracción de derechos de autor";
"report.title.impersonation" = "Suplantación de identidad";
"report.title.scam" = "Acoso u hostigamiento";
"report.title.terrorism" = "Terrorismo";
"report.error.notReported" = "Error al enviar el informe.";
// Mark: Following requests.
"followingRequests.navigationBar.title" = "Solicitudes de seguimiento";
"followingRequests.title.approve" = "Aprobar";
"followingRequests.title.reject" = "Rechazar";
"followingRequests.error.approve" = "Error al aprobar la solicitud.";
"followingRequests.error.reject" = "Error al rechazar la solicitud.";

View File

@ -1,371 +0,0 @@
// MARK: Common strings.
"global.title.contentWarning" = "Eduki hunkigarria";
"global.title.seePost" = "Ikusi bidalketa";
"global.title.refresh" = "Freskatu";
"global.title.momentsAgo" = "oraintxe bertan";
"global.title.success" = "Primeran";
"global.title.photoSaved" = "Argazkia gorde da.";
"global.title.ok" = "Ados";
"global.title.showMore" = "Erakutsi gehiago";
"global.title.showLess" = "Erakutsi gutxiago";
"global.title.close" = "Itxi";
"global.error.refreshingCredentialsTitle" = "Egiaztagirien freskatzeak huts egin du.";
"global.error.refreshingCredentialsSubtitle" = "Hasi saioa berriro Pixelfeden.";
// MARK: Global errors.
"global.error.unexpected" = "Espero ez zen errorea.";
"global.error.statusesNotRetrieved" = "Ez dira egoerak eskuratu.";
"global.error.errorDuringDownloadStatuses" = "Errorea zerbitzaritik egoerak eskuratzean.";
"global.error.errorDuringDownloadHashtag" = "Errorea zerbitzaritik traolak eskuratzean.";
"global.error.hashtagNotExists" = "Traola ez da lehendik existitzen.";
"global.error.errorDuringImageDownload" = "Ezin da irudia eskuratu.";
"global.error.canceledImageDownload" = "Irudiaren deskarga bertan behera utzi da.";
"global.error.errorDuringDataLoad" = "Datuen kargak huts egin du.";
"global.error.errorDuringUserRead" = "Ezin izan da erabiltzailearen kontua eskuratu.";
"global.error.badUrlServer" = "Zerbitzariaren URL okerra.";
"global.error.accessTokenNotFound" = "Ez da sarbide-tokena aurkitu.";
"global.error.errorDuringDownloadStatus" = "Errorea zerbitzaritik egoera eskuratzean.";
"global.error.errorDuringPurchaseVerification" = "Erosketaren egiaztaketak huts egin du.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Hasiera";
"mainview.tab.localTimeline" = "Lokala";
"mainview.tab.federatedTimeline" = "Federatua";
"mainview.tab.trendingPhotos" = "Argazkiak";
"mainview.tab.trendingTags" = "Traolak";
"mainview.tab.trendingAccounts" = "Kontuak";
"mainview.tab.userProfile" = "Profila";
"mainview.tab.notifications" = "Jakinarazpenak";
"mainview.tab.search" = "Bilatu";
"mainview.tab.trending" = "Bogan";
// MARK: Main view (leading navigation bar).
"mainview.menu.settings" = "Ezarpenak";
// MARK: Main view (error notifications).
"mainview.error.switchAccounts" = "Ezin da kontua aldatu.";
// MARK: Home timeline.
"home.title.allCaughtUp" = "Egunean zaude";
"home.title.noPhotos" = "Argazkirik ez.";
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
"statuses.navigationBar.localTimeline" = "Lokala";
"statuses.navigationBar.federatedTimeline" = "Federatua";
"statuses.navigationBar.favourites" = "Gogokoak";
"statuses.navigationBar.bookmarks" = "Laster-markak";
"statuses.title.noPhotos" = "Argazkirik ez.";
"statuses.title.tagFollowed" = "Traolari jarraitzen diozu.";
"statuses.title.tagUnfollowed" = "Traola jarraitzeari utzi diozu.";
"statuses.error.loadingStatusesFailed" = "Egoerak kargatzeak huts egin du.";
"statuses.error.tagFollowFailed" = "Traolari jarraitzeak huts egin du.";
"statuses.error.tagUnfollowFailed" = "Traolari jarraitzeari uzteak huts egin du.";
// Mark: Search view.
"search.navigationBar.title" = "Bilatu";
"search.title.placeholder" = "Bilatu...";
"search.title.usersWith" = "%@ duten erabiltzaileak";
"search.title.goToUser" = "Joan %@ erabiltzailera";
"search.title.hashtagWith" = "%@ duten traolak";
"search.title.goToHashtag" = "Joan %@ traolara";
// Mark: Trending statuses.
"trendingStatuses.navigationBar.title" = "Argazkiak";
"trendingStatuses.title.daily" = "Egunekoak";
"trendingStatuses.title.monthly" = "Hilabetekoak";
"trendingStatuses.title.yearly" = "Urtekoak";
"trendingStatuses.error.loadingStatusesFailed" = "Egoerak kargatzeak huts egin du.";
"trendingStatuses.title.noPhotos" = "Argazkirik ez.";
// Mark: Trending tags.
"trendingTags.navigationBar.title" = "Traolak";
"trendingTags.title.noTags" = "Traolarik ez.";
"trendingTags.title.amountOfPosts" = "%d bidalketa";
"trendingTags.error.loadingTagsFailed" = "Traolak kargatzeak huts egin du.";
// Mark: Trending accounts.
"trendingAccounts.navigationBar.title" = "Kontuak";
"trendingAccounts.title.noAccounts" = "Inor ez.";
"trendingAccounts.error.loadingAccountsFailed" = "Kontuak kargatzeak huts egin du.";
// Mark: User profile view.
"userProfile.title.openInBrowser" = "Ireki nabigatzailean";
"userProfile.title.share" = "Partekatu";
"userProfile.title.unmute" = "Utzi mututzeari";
"userProfile.title.mute" = "Mututu";
"userProfile.title.unblock" = "Utzi blokeatzeari";
"userProfile.title.block" = "Blokeatu";
"userProfile.title.favourites" = "Gogokoak";
"userProfile.title.bookmarks" = "Laster-markak";
"userProfile.title.posts" = "Bidalketa";
"userProfile.title.followers" = "Jarraitzaile";
"userProfile.title.following" = "Jarraitzen";
"userProfile.title.joined" = "%@ egin zuen bat";
"userProfile.title.unfollow" = "Utzi jarraitzeari";
"userProfile.title.follow" = "Jarraitu";
"userProfile.title.instance" = "Instantziari buruzko informazioa";
"userProfile.title.blocks" = "Blokeatutako kontuak";
"userProfile.title.mutes" = "Mutututako kontuak";
"userProfile.title.muted" = "Kontua mututu da";
"userProfile.title.unmuted" = "Kontua mututzeari utzi zaio";
"userProfile.title.blocked" = "Kontua blokeatu da";
"userProfile.title.unblocked" = "Kontua blokeatzeari utzi zaio";
"userProfile.title.report" = "Salatu";
"userProfile.title.followsYou" = "Jarraitzen dizu";
"userProfile.title.requestFollow" = "Egin jarraitzeko eskaera";
"userProfile.title.cancelRequestFollow" = "Bertan behera utzi jarraitzeko eskaera";
"userProfile.title.followRequests" = "Jarraipen-eskaerak";
"userProfile.title.privateProfileTitle" = "Profil hau pribatua da.";
"userProfile.title.privateProfileSubtitle" = "Baimendutako jarraitzaileek soilik ikus ditzakete argazkiak.";
"userProfile.error.notExists" = "Kontua ez da existitzen.";
"userProfile.error.loadingAccountFailed" = "Errorea zerbitzaritik kontua eskuratzean.";
"userProfile.error.muting" = "Mututu/Mututzeari uzteak huts egin du.";
"userProfile.error.block" = "Blokeatu/Blokeatzeari uzteak huts egin du.";
"userProfile.error.relationship" = "Harreman ekintzak huts egin du.";
"userProfile.title.edit" = "Editatu";
"userProfile.title.muted" = "Mutututa";
"userProfile.title.blocked" = "Blokeatuta";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Jakinarazpenak";
"notifications.title.noNotifications" = "Ez dago jakinarazpenik.";
"notifications.title.followedYou" = "jarraitu dizu";
"notifications.title.mentionedYou" = "aipatu zaitu";
"notifications.title.boosted" = "bultzatu du";
"notifications.title.favourited" = "gogoko du";
"notifications.title.postedStatus" = "argitaratu du";
"notifications.title.followRequest" = "jarraipen-eskaera bidali dizu";
"notifications.title.poll" = "bozketa";
"notifications.title.updatedStatus" = "egoera eguneratu du";
"notifications.title.signedUp" = "izena eman du";
"notifications.title.newReport" = "txosten berria";
"notifications.error.loadingNotificationsFailed" = "Jakinarazpenak kargatzeak huts egin du.";
// Mark: Compose view.
"compose.navigationBar.title" = "Idatzi";
"compose.title.everyone" = "Edonorentzat ikusgai";
"compose.title.unlisted" = "Zerrendatu gabea";
"compose.title.followers" = "Jarraitzaileentzat ikusgai";
"compose.title.attachPhotoFull" = "Erantsi argazkia eta idatzi buruan duzuna";
"compose.title.attachPhotoMini" = "Idatzi buruan duzuna";
"compose.title.publish" = "Argitaratu";
"compose.title.cancel" = "Utzi";
"compose.title.writeContentWarning" = "Idatzi edukiari buruzko oharra";
"compose.title.commentsWillBeDisabled" = "Iruzkinak ezgaituko dira";
"compose.title.statusPublished" = "Egoera argitaratu da";
"compose.title.tryToUpload" = "Saiatu igotzen";
"compose.title.delete" = "Ezabatu";
"compose.title.edit" = "Editatu";
"compose.title.photos" = "Argazki-liburutegia";
"compose.title.camera" = "Egin argazkia";
"compose.title.files" = "Arakatu fitxategiak";
"compose.title.missingAltTexts" = "ALT testurik ez";
"compose.title.missingAltTextsWarning" = "Irudiren bat ez da ikusmen urritasuna dutenentzat deskribatu. Argazkiok argitaratu nahi dituzu hala ere?";
"compose.error.loadingPhotosFailed" = "Ezin da liburutegiko irudia eskuratu.";
"compose.error.postingPhotoFailed" = "Errorea argazkia argitaratzean.";
"compose.error.postingStatusFailed" = "Errorea egoera argitaratzean.";
// Mark: Photo editor view.
"photoEdit.navigationBar.title" = "Argazkiaren xehetasunak";
"photoEdit.title.photo" = "Argazkia";
"photoEdit.title.accessibility" = "Irisgarritasuna";
"photoEdit.title.accessibilityDescription" = "Ikusmen arazoak dituztenentzat deskribapena";
"photoEdit.title.save" = "Gorde";
"photoEdit.title.cancel" = "Utzi";
"photoEdit.error.updatePhotoFailed" = "Errorea argazkia eguneratzean.";
// Mark: Place selector view.
"placeSelector.navigationBar.title" = "Tokiak";
"placeSelector.title.search" = "Bilatu...";
"placeSelector.title.buttonSearch" = "Bilatu";
"placeSelector.title.cancel" = "Utzi";
"placeSelector.error.loadingPlacesFailed" = "Jakinarazpenak kargatzeak huts egin du.";
// Mark: Settings view.
"settings.navigationBar.title" = "Ezarpenak";
"settings.title.close" = "Itxi";
"settings.title.version" = "Bertsioa";
"settings.title.accounts" = "Kontuak";
"settings.title.newAccount" = "Gehitu kontua";
"settings.title.accent" = "Kolore nagusia";
"settings.title.theme" = "Gaia";
"settings.title.system" = "Sistemak darabilena";
"settings.title.light" = "Argia";
"settings.title.dark" = "Iluna";
"settings.title.avatar" = "Abatarra";
"settings.title.circle" = "Biribila";
"settings.title.rounderRectangle" = "Biribildutako ertzak";
"settings.title.other" = "Beste batzuk";
"settings.title.thirdParty" = "Hirugarrenak";
"settings.title.reportBug" = "Eman errore baten berri";
"settings.title.githubIssues" = "Erroreak Github-en";
"settings.title.follow" = "Jarrai nazazu";
"settings.title.support" = "Eman babesa";
"settings.title.thankYouTitle" = "Eskerrik asko 💕";
"settings.title.thankYouMessage" = "Mila esker erosketagatik. Erosketa handi eta txikiek gure bezeroei kalitatezko produkturik onenak eskaintzeko ametsari eusten laguntzen digute. Espero dugu Vernissage gustuko izatea.";
"settings.title.thankYouClose" = "Itxi";
"settings.title.haptics" = "Hobespen haptikoak";
"settings.title.hapticsTabSelection" = "Fitxak hautatzean";
"settings.title.hapticsButtonPress" = "Botoietan tap egitean";
"settings.title.hapticsListRefresh" = "Zerrendak freskatzean";
"settings.title.hapticsAnimationFinished" = "Animazioak amaitzean";
"settings.title.mediaSettings" = "Multimedia hobespenak";
"settings.title.alwaysShowSensitiveTitle" = "Erakutsi beti NSFW edukia";
"settings.title.alwaysShowSensitiveDescription" = "NSFW (Lanerako Egokia Izan Ez Daitekeen Edukia) gisa markatutako multimedia edukia ohartarazpenik gabe erakutsiko da";
"settings.title.alwaysShowAltTitle" = "Erakutsi testu alternatiboa";
"settings.title.alwaysShowAltDescription" = "Testu alternatiboa xehetasunen pantailan erakutsiko da, baldin badago";
"settings.title.general" = "Orokorra";
"settings.title.applicationIcon" = "Aplikazioaren ikonoa";
"settings.title.followVernissage" = "Jarraitu Vernissage-ri";
"settings.title.mastodonAccount" = "Mastodon kontua";
"settings.title.pixelfedAccount" = "Pixelfed kontua";
"settings.title.openPage" = "Ireki";
"settings.title.privacyPolicy" = "Pribatutasun politika";
"settings.title.terms" = "Erabilera baldintzak";
"settings.title.sourceCode" = "Iturburu kodea";
"settings.title.rate" = "Baloratu Vernissage";
"settings.title.socials" = "Gizarte-sareak";
"settings.title.menuPosition" = "Menuaren kokapena";
"settings.title.topMenu" = "Nabigazio barra";
"settings.title.bottomRightMenu" = "Behe eskumaldean";
"settings.title.bottomLeftMenu" = "Behe ezkerraldean";
"settings.title.showAvatars" = "Erakutsi abatarrak";
"settings.title.showAvatarsOnTimeline" = "Abatarrak denbora-lerroan erakutsiko dira";
"settings.title.showFavourite" = "Erakutsi gogokoak";
"settings.title.showFavouriteOnTimeline" = "Gogokoak denbora-lerroan erakutsiko dira";
"settings.title.showAltText" = "Erakutsi ALT ikurra";
"settings.title.showAltTextOnTimeline" = "ALT ikurra (deskribapena edo testu alternatiboa dagoenaren seinale) denbora-lerroan erakutsiko da";
"settings.title.warnAboutMissingAltTitle" = "Abisatu ALT ahaztu bazait";
"settings.title.warnAboutMissingAltDescription" = "Irudiren batek deskribapenik ez badu, argitaratu baino lehen abisua erakutsiko da.";
// Mark: Signin view.
"signin.navigationBar.title" = "Hasi saioa Pixelfed-en";
"signin.title.serverAddress" = "Zerbitzariaren helbidea";
"signin.title.signIn" = "Hasi saioa";
"signin.title.enterServerAddress" = "Sartu zerbitzariaren helbidea";
"signin.title.howToJoinLink" = "Nola batu Pixelfed-era";
"signin.title.chooseServer" = "Edo aukeratu Pixelfed zerbitzaria";
"signin.title.amountOfUsers" = "%d erabiltzaile";
"signin.title.amountOStatuses" = "%d egoera";
"signin.error.communicationFailed" = "Zerbitzariarekin komunikazioak huts egin du.";
// Mark: Status view.
"status.navigationBar.title" = "Xehetasunak";
"status.title.uploaded" = ">";
"status.title.via" = "%@ bidez";
"status.title.reboostedBy" = "Bultzatu dutenak";
"status.title.favouritedBy" = "Gogoko egin dutenak";
"status.title.openInBrowser" = "Ireki nabigatzailean";
"status.title.shareStatus" = "Partekatu egoera";
"status.title.yourStatus" = "Zure egoera";
"status.title.delete" = "Ezabatu";
"status.title.reboosted" = "Bultzatua";
"status.title.unreboosted" = "Bultzada kendua";
"status.title.favourited" = "Gogoko egina";
"status.title.unfavourited" = "Gogoko egiteari utzia";
"status.title.bookmarked" = "Laster-marka jarria";
"status.title.unbookmarked" = "Laster-marka kendua";
"status.title.statusDeleted" = "Egoera ezabatua";
"status.title.reboost" = "Bultzatu";
"status.title.unreboost" = "Kendu bultzada";
"status.title.favourite" = "Egin gogoko";
"status.title.unfavourite" = "Kendu gogokoa";
"status.title.bookmark" = "Jarri laster-marka";
"status.title.unbookmark" = "Kendu laster-marka";
"status.title.comment" = "Egin iruzkina";
"status.title.report" = "Salatu";
"status.title.saveImage" = "Gorde irudia";
"status.title.showMediaDescription" = "Erakutsi multimediaren deskribapena";
"status.title.mediaDescription" = "Multimediaren deskribapena";
"status.title.shareImage" = "Partekatu irudia";
"status.title.altText" = "ALT";
"status.error.loadingStatusFailed" = "Egoera kargatzeak huts egin du.";
"status.error.notFound" = "Egoera ez da dagoeneko existitzen.";
"status.error.loadingCommentsFailed" = "Ezin dira iruzkinak eskuratu.";
"status.error.reboostFailed" = "Bultzadak huts egin du.";
"status.error.favouriteFailed" = "Gogokoak huts egin du.";
"status.error.bookmarkFailed" = "Laster-markak huts egin du.";
"status.error.deleteFailed" = "Ezabatzeak huts egin du.";
// Mark: Accounts view.
"accounts.navigationBar.followers" = "Jarraitzaile";
"accounts.navigationBar.following" = "Jarraitzen";
"accounts.navigationBar.favouritedBy" = "Honek gogoko egina";
"accounts.navigationBar.reboostedBy" = "Honek bultzatua";
"accounts.navigationBar.blocked" = "Blokeatutako kontuak";
"accounts.navigationBar.mutes" = "Mutututako kontuak";
"accounts.title.noAccounts" = "Inor ez.";
"accounts.error.loadingAccountsFailed" = "Kontuak kargatzeak huts egin du.";
// Mark: Third party view.
"thirdParty.navigationBar.title" = "Hirugarrenak";
// Mark: Widget view.
"widget.title.photoDescription" = "Widgeta Pixelfed-eko argazkiekin.";
"widget.title.qrCodeDescription" = "Widgeta zure Pixelfed-eko profilaren QR kodearekin.";
// Mark: In-app purchases.
"purchase.donut.title" = "Opila";
"purchase.donut.description" = "Eros diezadazu opil bat.";
"purchase.coffee.title" = "Kafea";
"purchase.coffee.description" = "Gonbida nazazu kafe bat hartzera.";
"purchase.cake.title" = "Kafea eta tarta";
"purchase.cake.description" = "Kafea eta tarta erosiko?";
// Mark: Edit profile.
"editProfile.navigationBar.title" = "Editatu profila";
"editProfile.title.displayName" = "Pantaila izena";
"editProfile.title.bio" = "Biografia";
"editProfile.title.website" = "Webgunea";
"editProfile.title.save" = "Gorde";
"editProfile.title.accountSaved" = "Profila eguneratu da.";
"editProfile.title.photoInfo" = "Aldatutako argazkia atzerapen txiki batekin ikusiko da aplikazioan eta web gunean.";
"editProfile.title.privateAccount" = "Babestutako kontua";
"editProfile.title.privateAccountInfo" = "Zure kontua babestuta dagoenean baimendutako pertsonek bakarrik ikus ditzakete zure argazkiak eta bideoak Pixelfed-en. Ez du eraginik izango dagoeneko jarraitzen dizutenengan.";
"editProfile.error.saveAccountFailed" = "Profila gordetzeak huts egin du.";
"editProfile.error.loadingAvatarFailed" = "Abatarra kargatzeak huts egin du.";
"editProfile.error.noProfileData" = "Ezin dira profileko datuak erakutsi.";
"editProfile.error.loadingAccountFailed" = "Errorea zerbitzaritik kontua eskuratzean.";
// Mark: Instance information.
"instance.navigationBar.title" = "Instantzia";
"instance.title.instanceInfo" = "Instantziari buruzko informazioa";
"instance.title.name" = "Izena";
"instance.title.address" = "Helbidea";
"instance.title.email" = "ePosta";
"instance.title.version" = "Bertsioa";
"instance.title.users" = "Erabiltzaileak";
"instance.title.posts" = "Bidalketak";
"instance.title.domains" = "Domeinuak";
"instance.title.registrations" = "Izen emateak";
"instance.title.approvalRequired" = "Onespena behar da";
"instance.title.rules" = "Instantziaren arauak";
"instance.title.contact" = "Harremana";
"instance.title.pixelfedAccount" = "Pixelfed kontua";
"instance.error.noInstanceData" = "Ezin dira instantziaren datuak erakutsi.";
"instance.error.loadingDataFailed" = "Errorea zerbitzaritik instantziaren datuak eskuratzean.";
// Mark: Report screen.
"report.navigationBar.title" = "Salatu";
"report.title.close" = "Itxi";
"report.title.send" = "Bidali";
"report.title.userReported" = "Erabiltzailea salatu da";
"report.title.postReported" = "Bidalketa salatu da";
"report.title.reportType" = "Urraketa mota";
"report.title.spam" = "Spama da";
"report.title.sensitive" = "Biluzia edo sexu-ekintza";
"report.title.abusive" = "Gorroto sustatzen duten hitzaldiak edo ikurrak";
"report.title.underage" = "Adingabea";
"report.title.violence" = "Bortizkeria edo erakunde arriskutsua";
"report.title.copyright" = "Egile-eskubideen urraketa";
"report.title.impersonation" = "Imitatzailea";
"report.title.scam" = "Bullyinga edo jazarpena";
"report.title.terrorism" = "Terrorismoa";
"report.error.notReported" = "Errorea salaketa bidaltzerakoan.";
// Mark: Following requests.
"followingRequests.navigationBar.title" = "Jarraipen-eskaerak";
"followingRequests.title.approve" = "Baimendu";
"followingRequests.title.reject" = "Baztertu";
"followingRequests.error.approve" = "Errorea eskaera baimentzean.";
"followingRequests.error.reject" = "Errorea eskaera baztertzean.";

View File

@ -1,371 +0,0 @@
// MARK: Common strings.
"global.title.contentWarning" = "Contenu sensible";
"global.title.seePost" = "Voir le post";
"global.title.refresh" = "Rafraîchir";
"global.title.momentsAgo" = "Il y a quelques instants";
"global.title.success" = "Succès";
"global.title.photoSaved" = "La photo a été sauvegardée.";
"global.title.ok" = "OK";
"global.title.showMore" = "Montrer plus";
"global.title.showLess" = "Montrer moins";
"global.title.close" = "Fermer";
"global.error.refreshingCredentialsTitle" = "Erreur d'actualisation des données d'identification.";
"global.error.refreshingCredentialsSubtitle" = "Veuillez vous connecter à nouveau à Pixelfed.";
// MARK: Global errors.
"global.error.unexpected" = "Erreur inattendue.";
"global.error.statusesNotRetrieved" = "Statuts non récupérés.";
"global.error.errorDuringDownloadStatuses" = "Erreur pendant le téléchargerment des statuts du serveur.";
"global.error.errorDuringDownloadHashtag" = "Erreur pendant le téléchargement des tags depuis le serveur.";
"global.error.hashtagNotExists" = "Le hashtag n'existe pas.";
"global.error.errorDuringImageDownload" = "Impossible de télécharger l'image.";
"global.error.canceledImageDownload" = "Le téléchargement de l'image a été annulé.";
"global.error.errorDuringDataLoad" = "Le chargement des données a échoué.";
"global.error.errorDuringUserRead" = "Impossible de récupérer les données de l'utilisateur.";
"global.error.badUrlServer" = "Mauvaise URL pour le serveur.";
"global.error.accessTokenNotFound" = "Le jeton d'accès n'est pas trouvé.";
"global.error.errorDuringDownloadStatus" = "Erreur durant le téléchargement du statut depuis le serveur.";
"global.error.errorDuringPurchaseVerification" = "Vérification d'achat échoué.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Accueil";
"mainview.tab.localTimeline" = "Local";
"mainview.tab.federatedTimeline" = "Fédéré";
"mainview.tab.trendingPhotos" = "Photos";
"mainview.tab.trendingTags" = "Tags";
"mainview.tab.trendingAccounts" = "Utilisateurs";
"mainview.tab.userProfile" = "Profil";
"mainview.tab.notifications" = "Notifications";
"mainview.tab.search" = "Rechercher";
"mainview.tab.trending" = "Tendance";
// MARK: Main view (leading navigation bar).
"mainview.menu.settings" = "Paramètres";
// MARK: Main view (error notifications).
"mainview.error.switchAccounts" = "Impossible de changer de compte.";
// MARK: Home timeline.
"home.title.allCaughtUp" = "Tout est à jour";
"home.title.noPhotos" = "Malheureusement, il n'y a pas de photos ici.";
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
"statuses.navigationBar.localTimeline" = "Local";
"statuses.navigationBar.federatedTimeline" = "Fédéré";
"statuses.navigationBar.favourites" = "Favoris";
"statuses.navigationBar.bookmarks" = "Marque-pages";
"statuses.title.noPhotos" = "Malheureusement, il n'y a pas de photos ici.";
"statuses.title.tagFollowed" = "Vous suivez ce tag.";
"statuses.title.tagUnfollowed" = "Vous ne suivez plus ce tag.";
"statuses.error.loadingStatusesFailed" = "Chargement des statuts impossible.";
"statuses.error.tagFollowFailed" = "Suivi de tag échoué.";
"statuses.error.tagUnfollowFailed" = "Ne plus suivre le tag a échoué.";
// Mark: Search view.
"search.navigationBar.title" = "Rechercher";
"search.title.placeholder" = "Rechercher...";
"search.title.usersWith" = "Utilisateurs avec %@";
"search.title.goToUser" = "Voir l'utilisateur %@";
"search.title.hashtagWith" = "Hashtags avec %@";
"search.title.goToHashtag" = "Voir le hashtag %@";
// Mark: Trending statuses.
"trendingStatuses.navigationBar.title" = "Photos";
"trendingStatuses.title.daily" = "Quotidien";
"trendingStatuses.title.monthly" = "Mensuel";
"trendingStatuses.title.yearly" = "Annuel";
"trendingStatuses.error.loadingStatusesFailed" = "Chargement des statuts échoué.";
"trendingStatuses.title.noPhotos" = "Malheureusement, il n'y a pas de photos ici.";
// Mark: Trending tags.
"trendingTags.navigationBar.title" = "Tags";
"trendingTags.title.noTags" = "Malheureusement, il n'y a pas de tags ici.";
"trendingTags.title.amountOfPosts" = "%d posts";
"trendingTags.error.loadingTagsFailed" = "Chargement des tags échoué.";
// Mark: Trending accounts.
"trendingAccounts.navigationBar.title" = "Utilisateurs";
"trendingAccounts.title.noAccounts" = "Malheureusement, il n'y a personne ici.";
"trendingAccounts.error.loadingAccountsFailed" = "Chargement des comptes échoué.";
// Mark: User profile view.
"userProfile.title.openInBrowser" = "Ouvrir dans un navigateur";
"userProfile.title.share" = "Partager";
"userProfile.title.unmute" = "Désactiver";
"userProfile.title.mute" = "Sourdine";
"userProfile.title.unblock" = "Déblouer";
"userProfile.title.block" = "Bloquer";
"userProfile.title.favourites" = "Favoris";
"userProfile.title.bookmarks" = "Marque-pages";
"userProfile.title.posts" = "Posts";
"userProfile.title.followers" = "Abonnés";
"userProfile.title.following" = "Abonnements";
"userProfile.title.joined" = "Joint %@";
"userProfile.title.unfollow" = "Ne plus suivre";
"userProfile.title.follow" = "Suivre";
"userProfile.title.instance" = "Information sur l'instance";
"userProfile.title.blocks" = "Comptes bloqués";
"userProfile.title.mutes" = "Comptes en sourdine";
"userProfile.title.muted" = "Compte mis en sourdine";
"userProfile.title.unmuted" = "Compte remis en actif";
"userProfile.title.blocked" = "Compte bloqué";
"userProfile.title.unblocked" = "Compte débloqué";
"userProfile.title.report" = "Rapport";
"userProfile.title.followsYou" = "Vous suit";
"userProfile.title.requestFollow" = "Demande de suivi";
"userProfile.title.cancelRequestFollow" = "Annuler la demande";
"userProfile.title.followRequests" = "Suivre les demandes";
"userProfile.title.privateProfileTitle" = "Ce profil est privé.";
"userProfile.title.privateProfileSubtitle" = "Seules les personnes approuvées peuvent voir les photos.";
"userProfile.error.notExists" = "Le compte n'existe pas.";
"userProfile.error.loadingAccountFailed" = "Erreur pendant le téléchargement du compte depuis le serveur.";
"userProfile.error.muting" = "L'action sourdine / réactivation a échoué.";
"userProfile.error.block" = "L'action bloquer / déblouquer a échoué.";
"userProfile.error.relationship" = "L'action de relation a échoué.";
"userProfile.title.edit" = "Editer";
"userProfile.title.muted" = "Sourdine";
"userProfile.title.blocked" = "Bloquer";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Notifications";
"notifications.title.noNotifications" = "Malheureusement, il n'y a rien ici.";
"notifications.title.followedYou" = "vous a suivi";
"notifications.title.mentionedYou" = "vous a mentionné";
"notifications.title.boosted" = "partagé";
"notifications.title.favourited" = "favori";
"notifications.title.postedStatus" = "statut posté";
"notifications.title.followRequest" = "demande de suivi";
"notifications.title.poll" = "sondage";
"notifications.title.updatedStatus" = "statut mis à jour";
"notifications.title.signedUp" = "s'inscrire";
"notifications.title.newReport" = "nouveau rapport";
"notifications.error.loadingNotificationsFailed" = "Chargement des notifications échoué.";
// Mark: Compose view.
"compose.navigationBar.title" = "Composer";
"compose.title.everyone" = "Tout le monde";
"compose.title.unlisted" = "Non listé";
"compose.title.followers" = "Abonnés";
"compose.title.attachPhotoFull" = "Joignez une photo et écrivez ce qui vous convient";
"compose.title.attachPhotoMini" = "Ecrivez ce qui vous convient";
"compose.title.publish" = "Publier";
"compose.title.cancel" = "Annuler";
"compose.title.writeContentWarning" = "Rédaction d'un avertissement sur le contenu";
"compose.title.commentsWillBeDisabled" = "Les commentaires seront désactivés";
"compose.title.statusPublished" = "Statuts publiés";
"compose.title.tryToUpload" = "Essayer de télécharger";
"compose.title.delete" = "Supprimer";
"compose.title.edit" = "Editer";
"compose.title.photos" = "Albums photos";
"compose.title.camera" = "Prendre une photo";
"compose.title.files" = "Parcourir les fichiers";
"compose.title.missingAltTexts" = "Manque un texte ALT";
"compose.title.missingAltTextsWarning" = "Toutes les images n'ont pas été décrites pour les malvoyants. Souhaitez-vous tout de même envoyer des photos ?";
"compose.error.loadingPhotosFailed" = "Impossible de récupérer l'image depuis la bibliothèque.";
"compose.error.postingPhotoFailed" = "Erreur pendant le post de la photo.";
"compose.error.postingStatusFailed" = "Erreur pendant le post du statut.";
// Mark: Photo editor view.
"photoEdit.navigationBar.title" = "Détails sur la photo";
"photoEdit.title.photo" = "Photo";
"photoEdit.title.accessibility" = "Accessibilité";
"photoEdit.title.accessibilityDescription" = "Description pour les malvoyants";
"photoEdit.title.save" = "Enregistrer";
"photoEdit.title.cancel" = "Annuler";
"photoEdit.error.updatePhotoFailed" = "Erreur pendant la mise à jour de la photo.";
// Mark: Place selector view.
"placeSelector.navigationBar.title" = "Lieux";
"placeSelector.title.search" = "Rechercher...";
"placeSelector.title.buttonSearch" = "Rechercher";
"placeSelector.title.cancel" = "Annuler";
"placeSelector.error.loadingPlacesFailed" = "Chargement des notifications échoué.";
// Mark: Settings view.
"settings.navigationBar.title" = "Paramètres";
"settings.title.close" = "Fermer";
"settings.title.version" = "Version";
"settings.title.accounts" = "Compte";
"settings.title.newAccount" = "Nouveau compte";
"settings.title.accent" = "Accent";
"settings.title.theme" = "Thème";
"settings.title.system" = "Système";
"settings.title.light" = "Clair";
"settings.title.dark" = "Sombre";
"settings.title.avatar" = "Avatar";
"settings.title.circle" = "Cercle";
"settings.title.rounderRectangle" = "Rectangle arrondi";
"settings.title.other" = "Autre";
"settings.title.thirdParty" = "Tiers";
"settings.title.reportBug" = "Rapporter un bogue";
"settings.title.githubIssues" = "Problèmes sur Github";
"settings.title.follow" = "Me suivre";
"settings.title.support" = "Support";
"settings.title.thankYouTitle" = "Merci 💕";
"settings.title.thankYouMessage" = "Merci pour votre achat. Les achats, petits et grands, nous aident à réaliser notre rêve de fournir des produits de la meilleure qualité à nos clients. Nous espérons que vous aimez Vernissage.";
"settings.title.thankYouClose" = "Fermer";
"settings.title.haptics" = "Haptique";
"settings.title.hapticsTabSelection" = "Sélection de l'onglet";
"settings.title.hapticsButtonPress" = "Appui sur un bouton";
"settings.title.hapticsListRefresh" = "Rafraîchir la liste";
"settings.title.hapticsAnimationFinished" = "Animation finie";
"settings.title.mediaSettings" = "Paramètres du media";
"settings.title.alwaysShowSensitiveTitle" = "Toujours montrer les NSFW";
"settings.title.alwaysShowSensitiveDescription" = "Forcer l'affichage de tous les media NFSW (contenu sensible) sans avertissement";
"settings.title.alwaysShowAltTitle" = "Afficher le texte alternatif";
"settings.title.alwaysShowAltDescription" = "Afficher le texte alternatif si présent sur l'écran des détails des statuts";
"settings.title.general" = "Général";
"settings.title.applicationIcon" = "Icône de l'application";
"settings.title.followVernissage" = "Suivre Vernissage";
"settings.title.mastodonAccount" = "Compte Mastodon";
"settings.title.pixelfedAccount" = "Compte Pixelfed";
"settings.title.openPage" = "Ouvrir";
"settings.title.privacyPolicy" = "Politique de confidentialité";
"settings.title.terms" = "Conditions générales d'utilisation";
"settings.title.sourceCode" = "Code source";
"settings.title.rate" = "Noter Vernissage";
"settings.title.socials" = "Social";
"settings.title.menuPosition" = "Position du menu";
"settings.title.topMenu" = "Barre de navigation";
"settings.title.bottomRightMenu" = "En bas à droite";
"settings.title.bottomLeftMenu" = "En bas à gauche";
"settings.title.showAvatars" = "Afficher les avatars";
"settings.title.showAvatarsOnTimeline" = "Les avatars sont affichés sur la timeline";
"settings.title.showFavourite" = "Afficher les favoris";
"settings.title.showFavouriteOnTimeline" = "Les favoris sont affichés sur la timeline";
"settings.title.showAltText" = "Afficher l'icône ALT";
"settings.title.showAltTextOnTimeline" = "L'icône ALT sera affichée sur la timeline";
"settings.title.warnAboutMissingAltTitle" = "Avertir de l'absence de texte ALT";
"settings.title.warnAboutMissingAltDescription" = "Un avertissement concernant les textes ALT manquants sera affiché avant la publication d'un nouveau message.";
// Mark: Signin view.
"signin.navigationBar.title" = "Se connecter à Pixelfed";
"signin.title.serverAddress" = "Adresse du serveur";
"signin.title.signIn" = "Connecter";
"signin.title.enterServerAddress" = "Entrer l'adresse du server";
"signin.title.howToJoinLink" = "Comment rejoindre Pixelfed";
"signin.title.chooseServer" = "Ou choisissez un sereveur Pixelfed";
"signin.title.amountOfUsers" = "%d Utilisateurs";
"signin.title.amountOStatuses" = "%d statuts";
"signin.error.communicationFailed" = "La communication avec le server a échoué.";
// Mark: Status view.
"status.navigationBar.title" = "Détails";
"status.title.uploaded" = "Envoyé";
"status.title.via" = "via %@";
"status.title.reboostedBy" = "Partagé par";
"status.title.favouritedBy" = "Favoris par";
"status.title.openInBrowser" = "Ouvrir dans un navigateur";
"status.title.shareStatus" = "Partger le statut";
"status.title.yourStatus" = "Votre statut";
"status.title.delete" = "Supprimer";
"status.title.reboosted" = "Partagé";
"status.title.unreboosted" = "Enlever le partage";
"status.title.favourited" = "Favorisé";
"status.title.unfavourited" = "Enlever le favoris";
"status.title.bookmarked" = "Marque-pages effectué";
"status.title.unbookmarked" = "Marque-pages enlevé";
"status.title.statusDeleted" = "Statut supprimé";
"status.title.reboost" = "Partagé";
"status.title.unreboost" = "Enlever le partage";
"status.title.favourite" = "Favoris";
"status.title.unfavourite" = "Enlever le favoris";
"status.title.bookmark" = "Marque-pages";
"status.title.unbookmark" = "Marque-pages enlevé";
"status.title.comment" = "Commenter";
"status.title.report" = "Rapport";
"status.title.saveImage" = "Enregistrer l'image";
"status.title.showMediaDescription" = "Afficher la description du media";
"status.title.mediaDescription" = "Description du media";
"status.title.shareImage" = "Partager l'image";
"status.title.altText" = "ALT";
"status.error.loadingStatusFailed" = "Chargement du statut échoué.";
"status.error.notFound" = "Le statut n'existe plus.";
"status.error.loadingCommentsFailed" = "Les commentaires ne peuvent être téléchargés.";
"status.error.reboostFailed" = "L'action de partage a échoué.";
"status.error.favouriteFailed" = "L'action de favoris a échoué.";
"status.error.bookmarkFailed" = "L'action de marque-pages a échoué.";
"status.error.deleteFailed" = "L'action de suppression a échoué.";
// Mark: Accounts view.
"accounts.navigationBar.followers" = "Abonnés";
"accounts.navigationBar.following" = "Abonnements";
"accounts.navigationBar.favouritedBy" = "Favorisé par";
"accounts.navigationBar.reboostedBy" = "Partagé par";
"accounts.navigationBar.blocked" = "Comptes bloqués";
"accounts.navigationBar.mutes" = "Comptes mis en sourdine";
"accounts.title.noAccounts" = "Malheureusement, il n'y a personne ici.";
"accounts.error.loadingAccountsFailed" = "Le chargement des comptes a échoué.";
// Mark: Third party view.
"thirdParty.navigationBar.title" = "Tiers";
// Mark: Widget view.
"widget.title.photoDescription" = "Widget avec des photos de Pixelfed.";
"widget.title.qrCodeDescription" = "Widget avec QR Code vers votre profil Pixelfed.";
// Mark: In-app purchases.
"purchase.donut.title" = "Beignet";
"purchase.donut.description" = "Offrez-moi un beignet.";
"purchase.coffee.title" = "Café";
"purchase.coffee.description" = "Offrez-moi un café.";
"purchase.cake.title" = "Café et gâteau";
"purchase.cake.description" = "Offrez-moi un café et un gâteau.";
// Mark: Edit profile.
"editProfile.navigationBar.title" = "Editer le profil";
"editProfile.title.displayName" = "Afficher le nom";
"editProfile.title.bio" = "Bio";
"editProfile.title.website" = "Site web";
"editProfile.title.save" = "Enregistrer";
"editProfile.title.accountSaved" = "Le profil a été mis à jour.";
"editProfile.title.photoInfo" = "La photo modifiée sera visible dans l'application et sur le site web avec un petit délai.";
"editProfile.title.privateAccount" = "Compte privé";
"editProfile.title.privateAccountInfo" = "Lorsque votre compte est privé, seules les personnes que vous autorisez peuvent voir vos photos et vidéos sur Pixelfed. Les personnes qui vous suivent déjà ne seront pas affectées.";
"editProfile.error.saveAccountFailed" = "Enregistrement du profil échoué.";
"editProfile.error.loadingAvatarFailed" = "Chargement de l'avatar échoué.";
"editProfile.error.noProfileData" = "Les données du profil ne peuvent pas être affichées.";
"editProfile.error.loadingAccountFailed" = "Erreur lors du téléchargement du compte depuis le serveur.";
// Mark: Instance information.
"instance.navigationBar.title" = "Instance";
"instance.title.instanceInfo" = "Information sur l'instance";
"instance.title.name" = "Nom";
"instance.title.address" = "Addresse";
"instance.title.email" = "Email";
"instance.title.version" = "Version";
"instance.title.users" = "Utilisateurs";
"instance.title.posts" = "Posts";
"instance.title.domains" = "Domaines";
"instance.title.registrations" = "Inscriptions";
"instance.title.approvalRequired" = "Approbation requise";
"instance.title.rules" = "Règles de l'instance";
"instance.title.contact" = "Contact";
"instance.title.pixelfedAccount" = "Compte Pixelfed";
"instance.error.noInstanceData" = "Les données d'instance ne peuvent pas être affichées.";
"instance.error.loadingDataFailed" = "Erreur lors du téléchargement des données d'instance depuis le serveur.";
// Mark: Report screen.
"report.navigationBar.title" = "Rapport";
"report.title.close" = "Fermer";
"report.title.send" = "Envoyer";
"report.title.userReported" = "L'utilisateur a été signalé";
"report.title.postReported" = "Le post a été signalé";
"report.title.reportType" = "Type d'abus";
"report.title.spam" = "C'est un spam";
"report.title.sensitive" = "Nudité ou activité sexuelle";
"report.title.abusive" = "Discours ou symboles haineux";
"report.title.underage" = "Compte mineur";
"report.title.violence" = "Violence ou organisations dangereuses";
"report.title.copyright" = "Violation des droits d'auteur";
"report.title.impersonation" = "Usurpation d'identité";
"report.title.scam" = "Intimidation ou harcèlement";
"report.title.terrorism" = "Le terrorisme";
"report.error.notReported" = "Erreur lors de l'envoi du rapport.";
// Mark: Following requests.
"followingRequests.navigationBar.title" = "Suivre les demandes";
"followingRequests.title.approve" = "Approuver";
"followingRequests.title.reject" = "Rejeter";
"followingRequests.error.approve" = "Erreur lors de l'approbation de la demande.";
"followingRequests.error.reject" = "Erreur lors du rejet de la demande.";

View File

@ -1,371 +0,0 @@
// MARK: Common strings.
"global.title.contentWarning" = "Wrażliwe treści";
"global.title.seePost" = "Pokaż zdjęcie";
"global.title.refresh" = "Odśwież";
"global.title.momentsAgo" = "chwilę temu";
"global.title.success" = "Sukces";
"global.title.photoSaved" = "Zdjęcie zostało zapisane.";
"global.title.ok" = "OK";
"global.title.showMore" = "Pokaż więcej";
"global.title.showLess" = "Pokaż mniej";
"global.title.close" = "Zamknij";
"global.error.refreshingCredentialsTitle" = "Błąd odświeżania danych uwierzytelniających.";
"global.error.refreshingCredentialsSubtitle" = "Prosimy o ponowne zalogowanie się do Pixelfed.";
// MARK: Global errors.
"global.error.unexpected" = "Wystąpił nieoczekiwany błąd.";
"global.error.statusesNotRetrieved" = "Statusy nie zostały pobrane.";
"global.error.errorDuringDownloadStatuses" = "Błąd podczas pobierania statusów.";
"global.error.errorDuringDownloadHashtag" = "Błąd podczas pobierania taga.";
"global.error.hashtagNotExists" = "Tag nie istnieje.";
"global.error.errorDuringImageDownload" = "Błąd podczas pobierania zdjęcia.";
"global.error.canceledImageDownload" = "Pobieranie zdjęcia zostało anulowane.";
"global.error.errorDuringDataLoad" = "Błąd podczas pobierania danych.";
"global.error.errorDuringUserRead" = "Błąd podczas odczytu danych użytkownika.";
"global.error.badUrlServer" = "Niepoprawny adres serwera.";
"global.error.accessTokenNotFound" = "Brak tokenu dostępu.";
"global.error.errorDuringDownloadStatus" = "Błąd podczas pobierania statusu.";
"global.error.errorDuringPurchaseVerification" = "Błąd podczas weryfikacji płatności.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Główna";
"mainview.tab.localTimeline" = "Lokalne";
"mainview.tab.federatedTimeline" = "Globalne";
"mainview.tab.trendingPhotos" = "Zdjęcia";
"mainview.tab.trendingTags" = "Tagi";
"mainview.tab.trendingAccounts" = "Użytkownicy";
"mainview.tab.userProfile" = "Profil";
"mainview.tab.notifications" = "Powiadomienia";
"mainview.tab.search" = "Wyszukaj";
"mainview.tab.trending" = "Popularne";
// MARK: Main view (leading navigation bar).
"mainview.menu.settings" = "Ustawienia";
// MARK: Main view (error notifications).
"mainview.error.switchAccounts" = "Błąd podczas przełączania kont.";
// MARK: Home timeline.
"home.title.allCaughtUp" = "Jesteś na bieżąco";
"home.title.noPhotos" = "Niestety nie ma jeszcze żadnych zdjęć.";
// MARK: Statuses timeline (local/federated/favourite/bookmarks etc.).
"statuses.navigationBar.localTimeline" = "Lokalne";
"statuses.navigationBar.federatedTimeline" = "Globalne";
"statuses.navigationBar.favourites" = "Polubione";
"statuses.navigationBar.bookmarks" = "Zakładki";
"statuses.title.noPhotos" = "Niestety nie ma jeszcze żadnych zdjęć.";
"statuses.title.tagFollowed" = "Od teraz śledzisz taga.";
"statuses.title.tagUnfollowed" = "Nie śledzisz już taga.";
"statuses.error.loadingStatusesFailed" = "Błąd podczas wczytywania statusów.";
"statuses.error.tagFollowFailed" = "Błąd podczas żądania śledzenia taga.";
"statuses.error.tagUnfollowFailed" = "Błąd podczas wyłączenia śledzenia taga.";
// Mark: Search view.
"search.navigationBar.title" = "Wyszukaj";
"search.title.placeholder" = "Wyszukaj...";
"search.title.usersWith" = "Użytkownicy zawierający %@";
"search.title.goToUser" = "Przejdź do użytkownika %@";
"search.title.hashtagWith" = "Tagi zawierające %@";
"search.title.goToHashtag" = "Przejdź do taga %@";
// Mark: Trending statuses.
"trendingStatuses.navigationBar.title" = "Zdjęcia";
"trendingStatuses.title.daily" = "Dzień";
"trendingStatuses.title.monthly" = "Miesiąc";
"trendingStatuses.title.yearly" = "Rok";
"trendingStatuses.error.loadingStatusesFailed" = "Błąd podczas wczytywania statusów.";
"trendingStatuses.title.noPhotos" = "Niestety nie ma jeszcze żadnych zdjęć.";
// Mark: Trending tags.
"trendingTags.navigationBar.title" = "Tags";
"trendingTags.title.noTags" = "Niestety nie ma jeszcze żadnych tagów.";
"trendingTags.title.amountOfPosts" = "%d statusów";
"trendingTags.error.loadingTagsFailed" = "Błąd podczas wczytywania tagów.";
// Mark: Trending accounts.
"trendingAccounts.navigationBar.title" = "Użytkownicy";
"trendingAccounts.title.noAccounts" = "Niestety nie ma tutaj nikogo.";
"trendingAccounts.error.loadingAccountsFailed" = "Błąd podczas wczytywania użytkownikow.";
// Mark: User profile view.
"userProfile.title.openInBrowser" = "Otwórz w przeglądarce";
"userProfile.title.share" = "Udostępnij";
"userProfile.title.unmute" = "Wyłącz wyciszenie";
"userProfile.title.mute" = "Wycisz";
"userProfile.title.unblock" = "Odblokuj";
"userProfile.title.block" = "Zablokuj";
"userProfile.title.favourites" = "Polubione";
"userProfile.title.bookmarks" = "Zakładki";
"userProfile.title.posts" = "Statusy";
"userProfile.title.followers" = "Obserwujący";
"userProfile.title.following" = "Obserwowani";
"userProfile.title.joined" = "Dołączył(a) %@";
"userProfile.title.unfollow" = "Przestań obserwować";
"userProfile.title.follow" = "Obserwuj";
"userProfile.title.instance" = "Informacje o instancji";
"userProfile.title.blocks" = "Zablokowane konta";
"userProfile.title.mutes" = "Wyciszone konta";
"userProfile.title.muted" = "Konto wyciszone";
"userProfile.title.unmuted" = "Wyciszenie wyłączone";
"userProfile.title.blocked" = "Konto zablokowane";
"userProfile.title.unblocked" = "Konto odblokowane";
"userProfile.title.report" = "Zgłoś";
"userProfile.title.followsYou" = "Obserwuje ciebie";
"userProfile.title.requestFollow" = "Poproś o obserwowanie";
"userProfile.title.cancelRequestFollow" = "Anuluj prośbę";
"userProfile.title.followRequests" = "Prośby o obserwowanie";
"userProfile.title.privateProfileTitle" = "To konto jest prywatne.";
"userProfile.title.privateProfileSubtitle" = "Tylko zaakceptowani użytkownicy mogą przeglądać zdjęcia.";
"userProfile.error.notExists" = "Konto nie istnieje.";
"userProfile.error.notExists" = "Błąd podczas pobierania danych użytkownika.";
"userProfile.error.mute" = "Błąd podczas wyciszania użytkownika.";
"userProfile.error.block" = "Błąd podczas blokowania/odblokowywania użytkownika.";
"userProfile.error.relationship" = "Błąd podczas zmiany relacji z użytkownikiem.";
"userProfile.title.edit" = "Edytuj";
"userProfile.title.muted" = "Wyciszony";
"userProfile.title.blocked" = "Zablokowany";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Powiadomienia";
"notifications.title.noNotifications" = "Niestety nic tutaj nie ma.";
"notifications.title.followedYou" = "obserwuje ciebie";
"notifications.title.mentionedYou" = "wspomniał ciebie";
"notifications.title.boosted" = "podbił";
"notifications.title.favourited" = "polubił";
"notifications.title.postedStatus" = "stworzył status";
"notifications.title.followRequest" = "chce obserwować";
"notifications.title.poll" = "ankieta";
"notifications.title.updatedStatus" = "zaktualizował status";
"notifications.title.signedUp" = "zalogował się";
"notifications.title.newReport" = "nowy raport";
"notifications.error.loadingNotificationsFailed" = "Błąd podczas wczytywania powiadomień.";
// Mark: Compose view.
"compose.navigationBar.title" = "Utwórz";
"compose.title.everyone" = "Publiczny";
"compose.title.unlisted" = "Publiczny (niewidoczny)";
"compose.title.followers" = "Tylko obserwujący";
"compose.title.attachPhotoFull" = "Dołącz zdjęcie i napisz, co myślisz";
"compose.title.attachPhotoMini" = "Wpisz, co masz na myśli";
"compose.title.publish" = "Wyślij";
"compose.title.cancel" = "Anuluj";
"compose.title.writeContentWarning" = "Napisz ostrzeżenie o treści";
"compose.title.commentsWillBeDisabled" = "Komentarze zostaną wyłączone";
"compose.title.statusPublished" = "Stan opublikowany";
"compose.title.tryToUpload" = "Ponów";
"compose.title.delete" = "Usuń";
"compose.title.edit" = "Edytuj";
"compose.title.photos" = "Biblioteka zdjęć";
"compose.title.camera" = "Zrób zdjęcie";
"compose.title.files" = "Przeglądaj pliki";
"compose.title.missingAltTexts" = "Brakuje tekstów ALT";
"compose.title.missingAltTextsWarning" = "Nie wszystkie zdjęcia zostały opisane dla niedowidzących. Czy pomimo tego chcesz je wysłać?";
"compose.error.loadingPhotosFailed" = "Nie można pobrać zdjęcia z biblioteki.";
"compose.error.postingPhotoFailed" = "Błąd podczas publikowania zdjęcia.";
"compose.error.postingStatusFailed" = "Błąd podczas wysyłania statusu.";
// Mark: Photo editor view.
"photoEdit.navigationBar.title" = "Szczegóły zdjęcia";
"photoEdit.title.photo" = "Zdjęcie";
"photoEdit.title.accessibility" = "Dostępność";
"photoEdit.title.accessibilityDescription" = "Opis dla osób niedowidzących";
"photoEdit.title.save" = "Zapisz";
"photoEdit.title.cancel" = "Anuluj";
"photoEdit.error.updatePhotoFailed" = "Błąd podczas aktualizowania zdjęcia.";
// Mark: Place selector view.
"placeSelector.navigationBar.title" = "Lokalizacja";
"placeSelector.title.search" = "Wyszukaj...";
"placeSelector.title.buttonSearch" = "Szukaj";
"placeSelector.title.cancel" = "Anuluj";
"placeSelector.error.loadingPlacesFailed" = "Błąd podczas wczytywanie lokalizacji.";
// Mark: Settings view.
"settings.navigationBar.title" = "Ustawienia";
"settings.title.close" = "Zamknij";
"settings.title.version" = "Wersja";
"settings.title.accounts" = "Konta";
"settings.title.newAccount" = "Dodaj konto";
"settings.title.accent" = "Akcent";
"settings.title.theme" = "Wygląd";
"settings.title.system" = "Systemowy";
"settings.title.light" = "Jasny";
"settings.title.dark" = "Ciemny";
"settings.title.avatar" = "Awatar";
"settings.title.circle" = "Okrągły";
"settings.title.rounderRectangle" = "Zaokrąglony kwadratowy";
"settings.title.other" = "Inne";
"settings.title.thirdParty" = "Zewnętrzne biblioteki";
"settings.title.reportBug" = "Zgłoś błąd";
"settings.title.githubIssues" = "Błędy na Github";
"settings.title.follow" = "Obserwuj mnie";
"settings.title.support" = "Wsparcie";
"settings.title.thankYouTitle" = "Dziękuję 💕";
"settings.title.thankYouMessage" = "Dziękujemy za twój zakup. Zakupy zarówno te duże, jak i te małe pomagają nam w realizacji marzenia o dostarczaniu naszym klientom produktów najwyższej jakości. Mamy nadzieję, że Vernissage spełnia Twoje oczekiwania.";
"settings.title.thankYouClose" = "Zamknij";
"settings.title.haptics" = "Haptyka";
"settings.title.hapticsTabSelection" = "Wybór zakładki";
"settings.title.hapticsButtonPress" = "Naciśnięcie przycisku";
"settings.title.hapticsListRefresh" = "Odświeżanie listy";
"settings.title.hapticsAnimationFinished" = "Zakończenie animacji";
"settings.title.mediaSettings" = "Ustawienia mediów";
"settings.title.alwaysShowSensitiveTitle" = "Zawsze pokazuj statusy NSFW";
"settings.title.alwaysShowSensitiveDescription" = "Wymuś pokazywanie statusów NFSW (czułych) bez ostrzeżeń";
"settings.title.alwaysShowAltTitle" = "Pokaż tekst alternatywny";
"settings.title.alwaysShowAltDescription" = "Pokaż alternatywny tekst, jeśli jest obecny na szczegółach statusu";
"settings.title.general" = "Ogólne";
"settings.title.applicationIcon" = "Ikona aplikacji";
"settings.title.followVernissage" = "Obserwuj Vernissage";
"settings.title.mastodonAccount" = "Konto Mastodon";
"settings.title.pixelfedAccount" = "Konto Pixelfed";
"settings.title.openPage" = "Otwórz";
"settings.title.privacyPolicy" = "Polityka prywatności";
"settings.title.terms" = "Zasady i warunki";
"settings.title.sourceCode" = "Kod źródłowy";
"settings.title.rate" = "Oceń Vernissage";
"settings.title.socials" = "Społeczności";
"settings.title.menuPosition" = "Pozycja menu";
"settings.title.topMenu" = "Panel tytułowy";
"settings.title.bottomRightMenu" = "Dolny prawy";
"settings.title.bottomLeftMenu" = "Dolny lewy";
"settings.title.showAvatars" = "Wyświetlaj awatary";
"settings.title.showAvatarsOnTimeline" = "Awatary będą widoczne na osiach zdjęć";
"settings.title.showFavourite" = "Wyświetlaj polubienia";
"settings.title.showFavouriteOnTimeline" = "Polubienia będą widoczne na osiach zdjęć";
"settings.title.showAltText" = "Wyświetlaj ikonę ALT";
"settings.title.showAltTextOnTimeline" = "Ikony ALT będą widonczne na osiach zdjęć";
"settings.title.warnAboutMissingAltTitle" = "Ostrzeganie o brakującym tekście ALT";
"settings.title.warnAboutMissingAltDescription" = "Ostrzeżenie o brakujących tekstach ALT będzie wyświetlane przed opublikowaniem nowego statusu.";
// Mark: Signin view.
"signin.navigationBar.title" = "Zaloguj się do Pixelfed";
"signin.title.serverAddress" = "Adres serwera";
"signin.title.signIn" = "Zaloguj się";
"signin.title.enterServerAddress" = "Wpisz adres serwera";
"signin.title.howToJoinLink" = "Jak przyłączyć się do Pixelfed";
"signin.title.chooseServer" = "Lub wybierz serwer Pixelfed";
"signin.title.amountOfUsers" = "%d użytkowników";
"signin.title.amountOStatuses" = "%d statusów";
"signin.error.communicationFailed" = "Błąd podczas komunikacji z serwerem.";
// Mark: Status view.
"status.navigationBar.title" = "Szczegóły";
"status.title.uploaded" = "Wysłano";
"status.title.via" = "przez %@";
"status.title.reboostedBy" = "Podbite przez";
"status.title.favouritedBy" = "Polubione przez";
"status.title.openInBrowser" = "Otwórz w przeglądarce";
"status.title.shareStatus" = "Udostępnij status";
"status.title.yourStatus" = "Twój status";
"status.title.delete" = "Usuń";
"status.title.reboosted" = "Podbite";
"status.title.unreboosted" = "Podbicie wycofane";
"status.title.favourited" = "Polubione";
"status.title.unfavourited" = "Polubienie wycofane";
"status.title.bookmarked" = "Dodane do zakładek";
"status.title.unbookmarked" = "Usunięte z zakładek";
"status.title.statusDeleted" = "Status usunięty";
"status.title.reboost" = "Podbij";
"status.title.unreboost" = "Cofnij podbicie";
"status.title.favourite" = "Polub";
"status.title.unfavourite" = "Cofnij polubienie";
"status.title.bookmark" = "Dodaj do zakładek";
"status.title.unbookmark" = "Usuń z zakładek";
"status.title.comment" = "Skomentuj";
"status.title.report" = "Zgłoś";
"status.title.saveImage" = "Zapisz zdjęcie";
"status.title.showMediaDescription" = "Pokaż opis zdjęcia";
"status.title.mediaDescription" = "Opis zdjęcia";
"status.title.shareImage" = "Udostępnij zdjęcie";
"status.title.altText" = "ALT";
"status.error.loadingStatusFailed" = "Błąd podczas wczytywanie statusu.";
"status.error.notFound" = "Status już nie istnieje.";
"status.error.loadingCommentsFailed" =" Błąd podczas wczytywanie komentarzy.";
"status.error.reboostFailed" = "Błąd podczas podbijania.";
"status.error.favouriteFailed" = "Błąd podczas polubiania.";
"status.error.bookmarkFailed" = "Błąd podczas dodawania/usuwania z zakładek.";
"status.error.deleteFailed" = "Błąd podczas usuwania.";
// Mark: Accounts view.
"accounts.navigationBar.followers" = "Obserwujący";
"accounts.navigationBar.following" = "Obserwowani";
"accounts.navigationBar.favouritedBy" = "Polubione przez";
"accounts.navigationBar.reboostedBy" = "Podbite przez";
"accounts.navigationBar.blocked" = "Zablokowani";
"accounts.navigationBar.mutes" = "Wyciszeni";
"accounts.title.noAccounts" = "Niestety nie ma tutaj nikogo.";
"accounts.error.loadingAccountsFailed" = "Błąd podczas wczytywania użytkownikow.";
// Mark: Third party view.
"thirdParty.navigationBar.title" = "Zewnętrzne biblioteki";
// Mark: Widget view.
"widget.title.photoDescription" = "Widget ze zdjęciami z Pixelfed.";
"widget.title.qrCodeDescription" = "Widget z QR kodem do profilu na Pixelfed.";
// Mark: In-app purchases.
"purchase.donut.title" = "Pączek";
"purchase.donut.description" = "Poczęstuj mnie pączkiem.";
"purchase.coffee.title" = "Kawa";
"purchase.coffee.description" = "Poczęstuj mnie kawą.";
"purchase.cake.title" = "Kawa z ciastkiem";
"purchase.cake.description" = "Poczęstuj mnie kawą i ciastkiem.";
// Mark: Edit profile.
"editProfile.navigationBar.title" = "Edutuj profil";
"editProfile.title.displayName" = "Wyświetlana nazwa";
"editProfile.title.bio" = "Bio";
"editProfile.title.website" = "Strona";
"editProfile.title.save" = "Zapisz";
"editProfile.title.accountSaved" = "Profil zaktualizowano.";
"editProfile.title.photoInfo" = "Zmienione zdjęcie będzie widoczne w aplikacji oraz na stronie z małym opóźnieniem.";
"editProfile.title.privateAccount" = "Konto prywatne";
"editProfile.title.privateAccountInfo" = "Kiedy Twoje konto jest prywatne, tylko osoby, które zaakceptujesz mogą oglądać Twoje zdjęcia i filmy na Pixelfed. Nie wpłynie to na Twoich obecnych obserwujących.";
"editProfile.error.saveAccountFailed" = "Błąd podczas aktualizacji profilu.";
"editProfile.error.loadingAvatarFailed" = "Błąd podczas wczytywania zdjęcia.";
"editProfile.error.noProfileData" = "Dane profilu nie mogą zostać wyświetlone.";
"editProfile.error.loadingAccountFailed" = "Błąd podczas pobierania profilu użytkownika.";
// Mark: Instance information.
"instance.navigationBar.title" = "Instancja";
"instance.title.instanceInfo" = "Informacja o instancji";
"instance.title.name" = "Nazwa";
"instance.title.address" = "Adres";
"instance.title.email" = "Email";
"instance.title.version" = "Wersja";
"instance.title.users" = "Użytkownicy";
"instance.title.posts" = "Statusów";
"instance.title.domains" = "Domen";
"instance.title.registrations" = "Rejestracja";
"instance.title.approvalRequired" = "Akeptowanie rejestracji";
"instance.title.rules" = "Reguły instancji";
"instance.title.contact" = "Kontakt";
"instance.title.pixelfedAccount" = "Konto Pixelfed";
"instance.error.noInstanceData" = "Dane instancji nie mogą zostać wyświetlone.";
"instance.error.loadingDataFailed" = "Błąd podczas pobierania danych instancji.";
// Mark: Report screen.
"report.navigationBar.title" = "Zgłoś";
"report.title.close" = "Zamknij";
"report.title.send" = "Wyślij";
"report.title.userReported" = "Użytkownik został zgłoszony.";
"report.title.postReported" = "Status został zgłoszony.";
"report.title.reportType" = "Typ nadużycia";
"report.title.spam" = "Spam";
"report.title.sensitive" = "Nagość lub aktywność seksualna";
"report.title.abusive" = "Mowa lub symbole nienawiści";
"report.title.underage" = "Konto niepełnoletniego";
"report.title.violence" = "Przemoc lub niebezpieczne organizacje";
"report.title.copyright" = "Naruszenie praw autorskich";
"report.title.impersonation" = "Podszywanie się";
"report.title.scam" = "Znęcanie się lub nękanie";
"report.title.terrorism" = "Terroryzm";
"report.error.notReported" = "Błąd podczas wysyłania zgłoszenia.";
// Mark: Following requests.
"followingRequests.navigationBar.title" = "Prośby o obserwowanie";
"followingRequests.title.approve" = "Zaakceptuj";
"followingRequests.title.reject" = "Odrzuć";
"followingRequests.error.approve" = "Błąd podczas akceptowania prośby.";
"followingRequests.error.reject" = "Błąd podczas odrzucania prośby.";

View File

@ -1,4 +1,4 @@
// swift-tools-version: 5.7
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
@ -7,9 +7,7 @@ let package = Package(
name: "PixelfedKit",
defaultLocalization: "en",
platforms: [
.iOS(.v16),
.macOS(.v12),
.watchOS(.v8)
.iOS(.v17)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.

View File

@ -8,7 +8,7 @@ import Foundation
import RegexBuilder
/// Link returned in header for paging feature/
public struct Link {
public struct Link: Codable {
/// Raw value of header link.
public let rawLink: String

View File

@ -7,7 +7,7 @@
import Foundation
/// Some of endpoint returns JSON data and additional information in header, like link for paging functionality.
public struct Linkable<T> where T: Codable {
public struct Linkable<T> : Codable where T: Codable {
/// Data retunred in HTTP reponse body (mostly JSON data/entities).
public let data: T
@ -20,3 +20,29 @@ public struct Linkable<T> where T: Codable {
self.link = link
}
}
public extension Linkable<[Status]> {
func getMinId() -> String? {
if let link = self.link {
return link.minId
}
if let firstItemId = self.data.first?.id {
return firstItemId
}
return nil
}
func getMaxId() -> String? {
if let link = self.link {
return link.maxId
}
if let lastItemId = self.data.last?.id {
return lastItemId
}
return nil
}
}

View File

@ -16,7 +16,7 @@ extension NetworkError: LocalizedError {
switch self {
case .notSuccessResponse(let response):
let statusCode = response.statusCode()
let localizedString = NSLocalizedString("global.error.notSuccessResponse",
bundle: Bundle.module,
comment: "It's error returned from remote server. Request URL: '\(response.url?.string ?? "unknown")'.")

View File

@ -0,0 +1,334 @@
{
"sourceLanguage" : "en",
"strings" : {
"global.error.notSuccessResponse" : {
"comment" : "It's error returned from remote server. Request URL: '(response.url?.string ?? \"unknown\")'.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Serverantwort: %@."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Server response: %@."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Respuesta del servidor: %@."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Zerbitzariaren erantzuna: %@."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Réponse du serveur : %@."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Odpowiedź serwera: %@."
}
}
}
},
"global.error.unknownError" : {
"comment" : "Response doesn't contains any information about request status.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unbekannter Fehler."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unexpected error."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Error inesperado."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Espero ez zen errorea."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Erreur inattendue."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nieznany błąd serwera."
}
}
}
},
"report.error.duplicate" : {
"comment" : "The report has already been sent.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Der Bericht wurde bereits gesendet."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The report has already been sent."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "El informe ya ha sido enviado."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Txostena bidali da dagoeneko."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Le rapport a déjà été envoyé."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Zgłoszenie zostało już wysłane."
}
}
}
},
"report.error.invalidObject" : {
"comment" : "Invalid object type.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ungültiges Objekt."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Invalid object type."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tipo de objeto no válido."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Elementu-mota ez da baliozkoa."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Type d'objet non valide."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Niepoprawny typ obiektu."
}
}
}
},
"report.error.invalidObjectId" : {
"comment" : "Incorrect object Id.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fehlerhafte ID."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Incorrect object Id."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Identificador de objeto incorrecto."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Elementuaren IDa ez da zuzena."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Identifiant d'object incorrect."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Niepoprawny Id obiektu."
}
}
}
},
"report.error.invalidParameters" : {
"comment" : "Invalid report parameters.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ungültige Parameter."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Invalid report parameters."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Parámetros de informe no válidos."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Txostenaren parametroak ez dira baliozkoak."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Paramètres de rapport non valides."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Niepoprawne parametry zgłoszenia."
}
}
}
},
"report.error.invalidType" : {
"comment" : "Invalid report type.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ungültiger Berichtstyp."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Invalid report type."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tipo de informe no válido."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Txosten-mota ez da baliozkoa."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Type de rapport non valide."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Niepoprawny typ raportu."
}
}
}
},
"report.error.noSelfReports" : {
"comment" : "Self-reporting is not allowed.",
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Du darfst Dich nicht selbst melden."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Self-reporting is not allowed."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "No se permite el autoinforme."
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ezin duzu zure burua salatu."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "L'autodéclaration n'est pas autorisée."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Zgłaszanie siebie jest niedozwolone."
}
}
}
}
},
"version" : "1.0"
}

View File

@ -37,4 +37,16 @@ public extension PixelfedClientAuthenticated {
return try await downloadJson(Tag.self, request: request)
}
func followedTags(maxId: MaxId? = nil,
sinceId: SinceId? = nil,
minId: MinId? = nil,
limit: Int? = nil
) async throws -> Linkable<[Tag]> {
let request = try Self.request(for: baseURL,
target: Pixelfed.Tags.followed(maxId, sinceId, minId, limit),
withBearerToken: token)
return try await downloadJsonWithLink([Tag].self, request: request)
}
}

View File

@ -11,15 +11,18 @@ public extension PixelfedClientAuthenticated {
maxId: EntityId? = nil,
sinceId: EntityId? = nil,
minId: EntityId? = nil,
limit: Int? = nil) async throws -> [Status] {
limit: Int? = nil,
includeReblogs: Bool? = nil,
timeoutInterval: Double? = nil) async throws -> Linkable<[Status]> {
let request = try Self.request(
for: baseURL,
target: Pixelfed.Timelines.home(maxId, sinceId, minId, limit),
withBearerToken: token
target: Pixelfed.Timelines.home(maxId, sinceId, minId, limit, includeReblogs),
withBearerToken: token,
timeoutInterval: timeoutInterval
)
return try await downloadJson([Status].self, request: request)
return try await downloadJsonWithLink([Status].self, request: request)
}
func getPublicTimeline(local: Bool? = nil,
@ -28,7 +31,7 @@ public extension PixelfedClientAuthenticated {
maxId: EntityId? = nil,
sinceId: EntityId? = nil,
minId: EntityId? = nil,
limit: Limit? = nil) async throws -> [Status] {
limit: Limit? = nil) async throws -> Linkable<[Status]> {
let request = try Self.request(
for: baseURL,
@ -36,7 +39,7 @@ public extension PixelfedClientAuthenticated {
withBearerToken: token
)
return try await downloadJson([Status].self, request: request)
return try await downloadJsonWithLink([Status].self, request: request)
}
func getTagTimeline(tag: String,
@ -46,7 +49,7 @@ public extension PixelfedClientAuthenticated {
maxId: EntityId? = nil,
sinceId: EntityId? = nil,
minId: EntityId? = nil,
limit: Int? = nil) async throws -> [Status] {
limit: Int? = nil) async throws -> Linkable<[Status]> {
let request = try Self.request(
for: baseURL,
@ -54,7 +57,7 @@ public extension PixelfedClientAuthenticated {
withBearerToken: token
)
return try await downloadJson([Status].self, request: request)
return try await downloadJsonWithLink([Status].self, request: request)
}
func setMarkers(_ markers: [Pixelfed.Markers.Timeline: EntityId]) async throws -> Markers {

View File

@ -1,11 +0,0 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Server response: %@.";
"global.error.unknownError" = "Unexpected error.";
// Mark: Report errors.
"report.error.noSelfReports" = "Self-reporting is not allowed.";
"report.error.invalidObjectId" = "Incorrect object Id.";
"report.error.duplicate" = "The report has already been sent.";
"report.error.invalidParameters" = "Invalid report parameters.";
"report.error.invalidType" = "Invalid report type.";
"report.error.invalidObject" = "Invalid object type.";

View File

@ -1,11 +0,0 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Respuesta del servidor: %@.";
"global.error.unknownError" = "Error inesperado.";
// Mark: Report errors.
"report.error.noSelfReports" = "No se permite el autoinforme.";
"report.error.invalidObjectId" = "Identificador de objeto incorrecto.";
"report.error.duplicate" = "El informe ya ha sido enviado.";
"report.error.invalidParameters" = "Parámetros de informe no válidos.";
"report.error.invalidType" = "Tipo de informe no válido.";
"report.error.invalidObject" = "Tipo de objeto no válido.";

View File

@ -1,11 +0,0 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Zerbitzariaren erantzuna: %@.";
"global.error.unknownError" = "Espero ez zen errorea.";
// Mark: Report errors.
"report.error.noSelfReports" = "Ezin duzu zure burua salatu.";
"report.error.invalidObjectId" = "Elementuaren IDa ez da zuzena.";
"report.error.duplicate" = "Txostena bidali da dagoeneko.";
"report.error.invalidParameters" = "Txostenaren parametroak ez dira baliozkoak.";
"report.error.invalidType" = "Txosten-mota ez da baliozkoa.";
"report.error.invalidObject" = "Elementu-mota ez da baliozkoa.";

View File

@ -1,11 +0,0 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Réponse du serveur : %@.";
"global.error.unknownError" = "Erreur inattendue.";
// Mark: Report errors.
"report.error.noSelfReports" = "L'autodéclaration n'est pas autorisée.";
"report.error.invalidObjectId" = "Identifiant d'object incorrect.";
"report.error.duplicate" = "Le rapport a déjà été envoyé.";
"report.error.invalidParameters" = "Paramètres de rapport non valides.";
"report.error.invalidType" = "Type de rapport non valide.";
"report.error.invalidObject" = "Type d'objet non valide.";

View File

@ -1,11 +0,0 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Odpowiedź serwera: %@.";
"global.error.unknownError" = "Nieznany błąd serwera.";
// Mark: Report errors.
"report.error.noSelfReports" = "Zgłaszanie siebie jest niedozwolone.";
"report.error.invalidObjectId" = "Niepoprawny Id obiektu.";
"report.error.duplicate" = "Zgłoszenie zostało już wysłane.";
"report.error.invalidParameters" = "Niepoprawne parametry zgłoszenia.";
"report.error.invalidType" = "Niepoprawny typ raportu.";
"report.error.invalidObject" = "Niepoprawny typ obiektu.";

View File

@ -11,6 +11,7 @@ extension Pixelfed {
case tag(Hashtag)
case follow(Hashtag)
case unfollow(Hashtag)
case followed(MaxId?, SinceId?, MinId?, Limit?)
}
}
@ -26,13 +27,15 @@ extension Pixelfed.Tags: TargetType {
return "\(apiPath)/\(hashtag)/follow"
case .unfollow(let hashtag):
return "\(apiPath)/\(hashtag)/unfollow"
case .followed:
return "/api/v1/followed_tags"
}
}
/// The HTTP method used in the request.
public var method: Method {
switch self {
case .tag:
case .tag, .followed(_, _, _, _):
return .get
case .follow, .unfollow:
return .post
@ -41,7 +44,36 @@ extension Pixelfed.Tags: TargetType {
/// The parameters to be incoded in the request.
public var queryItems: [(String, String)]? {
return nil
var params: [(String, String)] = []
var maxId: MaxId?
var sinceId: SinceId?
var minId: MinId?
var limit: Limit?
switch self {
case .followed(let paramMaxId, let paramSinceId, let paramMinId, let paramLimit):
maxId = paramMaxId
sinceId = paramSinceId
minId = paramMinId
limit = paramLimit
default: break
}
if let maxId {
params.append(("max_id", maxId))
}
if let sinceId {
params.append(("since_id", sinceId))
}
if let minId {
params.append(("min_id", minId))
}
if let limit {
params.append(("limit", "\(limit)"))
}
return params
}
public var headers: [String: String]? {

View File

@ -8,7 +8,7 @@ import Foundation
extension Pixelfed {
public enum Timelines {
case home(MaxId?, SinceId?, MinId?, Limit?)
case home(MaxId?, SinceId?, MinId?, Limit?, Bool?)
case pub(Bool?, Bool?, Bool?, MaxId?, SinceId?, MinId?, Limit?)
case tag(String, Bool?, Bool?, Bool?, MaxId?, SinceId?, MinId?, Limit?)
}
@ -43,6 +43,7 @@ extension Pixelfed.Timelines: TargetType {
var local: Bool?
var remote: Bool?
var onlyMedia: Bool?
var includeReblogs: Bool?
var maxId: MaxId?
var sinceId: SinceId?
var minId: MinId?
@ -58,34 +59,48 @@ extension Pixelfed.Timelines: TargetType {
sinceId = paramSinceId
minId = paramMinId
limit = paramLimit
case .home(let paramMaxId, let paramSinceId, let paramMinId, let paramLimit):
case .home(let paramMaxId, let paramSinceId, let paramMinId, let paramLimit, let paramIncludeReblogs):
maxId = paramMaxId
sinceId = paramSinceId
minId = paramMinId
limit = paramLimit
includeReblogs = paramIncludeReblogs
}
if let maxId {
params.append(("max_id", maxId))
}
if let sinceId {
params.append(("since_id", sinceId))
}
if let minId {
params.append(("min_id", minId))
}
if let limit {
params.append(("limit", "\(limit)"))
}
if let local {
params.append(("local", local.asString))
}
if let remote {
params.append(("remote", remote.asString))
}
if let onlyMedia {
params.append(("only_media", onlyMedia.asString))
}
if let includeReblogs, includeReblogs == true {
params.append(("include_reblogs", includeReblogs.asString))
}
params.append(("_t", String.randomString(length: 8)))
return params
}

View File

@ -24,17 +24,27 @@ Thank you in advance for any, even the smallest help, with the development of th
## Translations
Creating new translation is pretty easy, all you need to do is to copy two folders:
- `Vernissage/Localization/en.lproj`
- `Vernissage/PixelfedKit/Sources/PixelfedKit/Resources/en.lproj`
Application is using new translation mechanism introduced in XCode 15 (xcstring). Here you can find description how this mechanism is working: [https://www.youtube.com/watch?v=jNbnwwLrJE8](https://www.youtube.com/watch?v=jNbnwwLrJE8).
In the name of the folders you have to put the code of the new language ([here](https://stackoverflow.com/a/13360348) you can find the languages codes).
Then you have to open files in these folders and translate them 🇯🇵🇫🇷🇨🇮🇧🇪. After translation create a Pull Request 👍.
In the applications we have several string catalogs:
- Localization/Localizable
- EnvironmentKit/Source/EnvironmentKit/Localizable
- WidgetKit/Source/WidgetKit/Localizable
- ServicesKit/Source/ServicesKit/Localizable
- PixelfedKit/Source/PixelfedKit/Localizable
- ClientKit/Source/ClientKit/Localizable
Right now it's very easy to find new (not translated yet) titles. Also you can mark titles which need some review.
However you need to have XCode 15 installed. There isn't right now good external tool that have similar features.
![translations](Resources/translations.png)
From time to time you have to come back and translate lines which has been added since the last translation.
## Technical debt
- Use auto generated resources (Color/Images) instead static extensions (how to do this in separete Swift Packages?)
- Enable swiftlint (https://github.com/realm/SwiftLint/issues/5053)
- Investigate new (iOS 17) Observables
- Check how to migrate to SwiftData (iOS 17)
Things that should be implemented in version 2.0:
- [ ] Use auto generated resources (Color/Images) instead static extensions (how to do this in separete Swift Packages?)
- [ ] Use ViewModels?
- [ ] Enable swiftlint (https://github.com/realm/SwiftLint/issues/5053)

BIN
Resources/translations.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -1,14 +1,13 @@
// swift-tools-version: 5.8
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "ServicesKit",
defaultLocalization: "en",
platforms: [
.iOS(.v16),
.macOS(.v12),
.watchOS(.v8)
.iOS(.v17)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.

View File

@ -28,7 +28,7 @@ public class CacheImageService {
self.add(data: imageData, for: url)
}
} catch {
ErrorService.shared.handle(error, message: "Downloading image into cache failed.")
ErrorService.shared.handle(error, message: "global.error.downloadingImageFailed")
}
}

View File

@ -5,24 +5,41 @@
//
import Foundation
import OSLog
import EnvironmentKit
import PixelfedKit
public class ErrorService {
public static let shared = ErrorService()
private init() { }
public func handle(_ error: Error, message: String, showToastr: Bool = false) {
let localizedMessage = NSLocalizedString(message, comment: "Error message")
public func handle(_ error: Error, message: LocalizedStringResource, showToastr: Bool = false) {
let localizedMessage = NSLocalizedString(message.key, comment: "Error message")
if showToastr {
switch error {
case is LocalizedError:
ToastrService.shared.showError(title: message, subtitle: error.localizedDescription)
default:
ToastrService.shared.showError(subtitle: localizedMessage)
ToastrService.shared.showError(title: "", subtitle: localizedMessage)
}
}
print("Error ['\(localizedMessage)']: \(error.localizedDescription)")
Logger.main.error("Error ['\(localizedMessage)']: \(error.localizedDescription)")
Logger.main.error("Error ['\(localizedMessage)']: \(error)")
}
public func handle(_ error: Error, localizedMessage: String, showToastr: Bool = false) {
if showToastr {
switch error {
case is LocalizedError:
ToastrService.shared.showError(localizedMessage: localizedMessage, subtitle: error.localizedDescription)
default:
ToastrService.shared.showError(title: "", subtitle: localizedMessage)
}
}
Logger.main.error("Error ['\(localizedMessage)']: \(error.localizedDescription)")
Logger.main.error("Error ['\(localizedMessage)']: \(error)")
}
}

View File

@ -28,7 +28,6 @@ public class HapticService {
impactGenerator.prepare()
}
@MainActor
public func fireHaptic(of type: HapticType) {
guard supportsHaptics else { return }

View File

@ -0,0 +1,80 @@
{
"sourceLanguage" : "en",
"strings" : {
"" : {
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : ""
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : ""
}
},
"eu" : {
"stringUnit" : {
"state" : "translated",
"value" : ""
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : ""
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : ""
}
}
}
},
"global.error.downloadingImageFailed" : {
"localizations" : {
"de" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Das Herunterladen des Bildes in den Cache ist fehlgeschlagen."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Downloading image into cache failed."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Error al descargar la imagen en la caché."
}
},
"eu" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Ezin izan da irudia cachean deskargatu."
}
},
"fr" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Le téléchargement de l'image dans le cache a échoué."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Błąd podczas pobieranie obrazków do pamięci podręcznej."
}
}
}
}
},
"version" : "1.0"
}

View File

@ -12,14 +12,14 @@ public class ToastrService {
public static let shared = ToastrService()
private init() { }
public func showSuccess(_ title: String, imageSystemName: String, subtitle: String? = nil) {
public func showSuccess(_ title: LocalizedStringResource, imageSystemName: String, subtitle: String? = nil) {
let image = self.createImage(systemName: imageSystemName, color: UIColor(Color.accentColor))
self.showSuccess(title, image: image, subtitle: subtitle)
self.showSuccess(title.key, image: image, subtitle: subtitle)
}
public func showSuccess(_ title: String, imageName: String, subtitle: String? = nil) {
public func showSuccess(_ title: LocalizedStringResource, imageName: String, subtitle: String? = nil) {
let image = self.createImage(name: imageName, color: UIColor(Color.accentColor))
self.showSuccess(title, image: image, subtitle: subtitle)
self.showSuccess(title.key, image: image, subtitle: subtitle)
}
private func showSuccess(_ title: String, image: UIImage?, subtitle: String? = nil) {
@ -39,17 +39,22 @@ public class ToastrService {
Drops.show(drop)
}
public func showError(title: String = "global.error.unexpected", imageSystemName: String = "ant.circle.fill", subtitle: String? = nil) {
public func showError(title: LocalizedStringResource, imageSystemName: String = "ant.circle.fill", subtitle: String? = nil) {
let image = self.createImage(systemName: imageSystemName, color: UIColor(Color.accentColor))
self.showError(title: title, image: image, subtitle: subtitle)
self.showError(title: title.key, image: image, subtitle: subtitle)
}
public func showError(localizedMessage: String, imageSystemName: String = "ant.circle.fill", subtitle: String? = nil) {
let image = self.createImage(systemName: imageSystemName, color: UIColor(Color.accentColor))
self.showError(title: localizedMessage, image: image, subtitle: subtitle)
}
public func showError(title: String = "global.error.unexpected", imageName: String, subtitle: String? = nil) {
public func showError(title: LocalizedStringResource, imageName: String, subtitle: String? = nil) {
let image = self.createImage(name: imageName, color: UIColor(Color.accentColor))
self.showError(title: title, image: image, subtitle: subtitle)
self.showError(title: title.key, image: image, subtitle: subtitle)
}
private func showError(title: String = "global.error.unexpected", image: UIImage?, subtitle: String? = nil) {
private func showError(title: String, image: UIImage?, subtitle: String? = nil) {
let drop = Drop(
title: NSLocalizedString(title, comment: "Error displayed to the user."),
subtitle: subtitle,

View File

@ -7,12 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
F80048032961850500E6868A /* AttachmentData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80047FF2961850500E6868A /* AttachmentData+CoreDataClass.swift */; };
F80048042961850500E6868A /* AttachmentData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048002961850500E6868A /* AttachmentData+CoreDataProperties.swift */; };
F80048052961850500E6868A /* StatusData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048012961850500E6868A /* StatusData+CoreDataClass.swift */; };
F80048062961850500E6868A /* StatusData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048022961850500E6868A /* StatusData+CoreDataProperties.swift */; };
F80048082961E6DE00E6868A /* StatusDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048072961E6DE00E6868A /* StatusDataHandler.swift */; };
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048092961EA1900E6868A /* AttachmentDataHandler.swift */; };
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F802884E297AEED5000BDD51 /* DatabaseError.swift */; };
F805DCF129DBEF83006A1FD9 /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F805DCF029DBEF83006A1FD9 /* ReportView.swift */; };
F808641429756666009F035C /* NotificationRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F808641329756666009F035C /* NotificationRowView.swift */; };
@ -22,13 +16,9 @@
F8210DD52966BB7E001D9973 /* Nuke in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD42966BB7E001D9973 /* Nuke */; };
F8210DD72966BB7E001D9973 /* NukeExtensions in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD62966BB7E001D9973 /* NukeExtensions */; };
F8210DD92966BB7E001D9973 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = F8210DD82966BB7E001D9973 /* NukeUI */; };
F8210DDD2966CF17001D9973 /* StatusData+Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DDC2966CF17001D9973 /* StatusData+Status.swift */; };
F8210DDF2966CFC7001D9973 /* AttachmentData+Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DDE2966CFC7001D9973 /* AttachmentData+Attachment.swift */; };
F8210DEA2966E4F9001D9973 /* AnimatePlaceholderModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */; };
F825F0C929F7A562008BD204 /* UserProfilePrivateAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F825F0C829F7A562008BD204 /* UserProfilePrivateAccountView.swift */; };
F825F0CB29F7CFC4008BD204 /* FollowRequestsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F825F0CA29F7CFC4008BD204 /* FollowRequestsView.swift */; };
F835082329BEF9C400DE3247 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
F835082429BEF9C400DE3247 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
F83CBEFB298298A1002972C8 /* ImageCarouselPicture.swift in Sources */ = {isa = PBXBuildFile; fileRef = F83CBEFA298298A1002972C8 /* ImageCarouselPicture.swift */; };
F84625E929FE2788002D3AF4 /* QRCodeWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84625E829FE2788002D3AF4 /* QRCodeWidget.swift */; };
F84625EB29FE28D4002D3AF4 /* QRCodeWidgetEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84625EA29FE28D4002D3AF4 /* QRCodeWidgetEntryView.swift */; };
@ -36,17 +26,12 @@
F84625F229FE2B6B002D3AF4 /* QRCodeWidgetEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84625F129FE2B6B002D3AF4 /* QRCodeWidgetEntry.swift */; };
F84625F429FE2BF9002D3AF4 /* QRCodeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84625F329FE2BF9002D3AF4 /* QRCodeProvider.swift */; };
F84625F829FE2C2F002D3AF4 /* AccountFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84625F729FE2C2F002D3AF4 /* AccountFetcher.swift */; };
F84625FB29FE393B002D3AF4 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = F84625FA29FE393B002D3AF4 /* QRCode */; };
F858906B29E1CC7A00D4BDED /* UIApplication+Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = F858906A29E1CC7A00D4BDED /* UIApplication+Window.swift */; };
F85D0C652ABA08F9002B3577 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F85D0C642ABA08F9002B3577 /* Assets.xcassets */; };
F85D4971296402DC00751DF7 /* AuthorizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D4970296402DC00751DF7 /* AuthorizationService.swift */; };
F85D4975296407F100751DF7 /* HomeTimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D4974296407F100751DF7 /* HomeTimelineService.swift */; };
F85D497729640A5200751DF7 /* ImageRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D497629640A5200751DF7 /* ImageRow.swift */; };
F85D497929640B9D00751DF7 /* ImagesCarousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D497829640B9D00751DF7 /* ImagesCarousel.swift */; };
F85D497D29640D5900751DF7 /* InteractionRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D497C29640D5900751DF7 /* InteractionRow.swift */; };
F85D497F296416C800751DF7 /* CommentsSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D497E296416C800751DF7 /* CommentsSectionView.swift */; };
F85D498329642FAC00751DF7 /* AttachmentData+Comperable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D498229642FAC00751DF7 /* AttachmentData+Comperable.swift */; };
F85D49852964301800751DF7 /* StatusData+Attachments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D49842964301800751DF7 /* StatusData+Attachments.swift */; };
F85D4DFE29B78C8400345267 /* HashtagModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85D4DFD29B78C8400345267 /* HashtagModel.swift */; };
F85DBF8F296732E20069BF89 /* AccountsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85DBF8E296732E20069BF89 /* AccountsView.swift */; };
F86167C6297FE6CC004D1F67 /* AvatarShapesSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F86167C5297FE6CC004D1F67 /* AvatarShapesSectionView.swift */; };
@ -61,29 +46,14 @@
F864F77829BB930000B13921 /* PhotoWidgetEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F864F77729BB930000B13921 /* PhotoWidgetEntry.swift */; };
F864F77A29BB94A800B13921 /* PixelfedKit in Frameworks */ = {isa = PBXBuildFile; productRef = F864F77929BB94A800B13921 /* PixelfedKit */; };
F864F77C29BB982100B13921 /* StatusFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = F864F77B29BB982100B13921 /* StatusFetcher.swift */; };
F864F77D29BB9A4600B13921 /* AttachmentData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80047FF2961850500E6868A /* AttachmentData+CoreDataClass.swift */; };
F864F77E29BB9A4900B13921 /* AttachmentData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048002961850500E6868A /* AttachmentData+CoreDataProperties.swift */; };
F864F78229BB9A6500B13921 /* StatusData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048012961850500E6868A /* StatusData+CoreDataClass.swift */; };
F864F78329BB9A6800B13921 /* StatusData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048022961850500E6868A /* StatusData+CoreDataProperties.swift */; };
F864F78429BB9A6E00B13921 /* ApplicationSettings+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */; };
F864F78529BB9A7100B13921 /* ApplicationSettings+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */; };
F864F78629BB9A7400B13921 /* AccountData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */; };
F864F78729BB9A7700B13921 /* AccountData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */; };
F864F78829BB9A7B00B13921 /* CoreDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2474295C37BB0006098B /* CoreDataHandler.swift */; };
F864F78529BB9A7100B13921 /* ApplicationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings.swift */; };
F864F78729BB9A7700B13921 /* AccountData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData.swift */; };
F864F78829BB9A7B00B13921 /* SwiftDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2474295C37BB0006098B /* SwiftDataHandler.swift */; };
F864F78929BB9A7D00B13921 /* AccountDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A229604161002E8F88 /* AccountDataHandler.swift */; };
F864F78A29BB9A8000B13921 /* ApplicationSettingsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A429604194002E8F88 /* ApplicationSettingsHandler.swift */; };
F864F78B29BB9A8300B13921 /* StatusDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048072961E6DE00E6868A /* StatusDataHandler.swift */; };
F864F78C29BB9A8500B13921 /* AttachmentDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048092961EA1900E6868A /* AttachmentDataHandler.swift */; };
F864F7A529BBA01D00B13921 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F864F7A429BBA01D00B13921 /* CoreDataError.swift */; };
F864F7A629BBA01D00B13921 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F864F7A429BBA01D00B13921 /* CoreDataError.swift */; };
F865B4CD2A024AD8008ACDFC /* StatusData+Faulty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865B4CC2A024AD8008ACDFC /* StatusData+Faulty.swift */; };
F865B4CE2A024AD8008ACDFC /* StatusData+Faulty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865B4CC2A024AD8008ACDFC /* StatusData+Faulty.swift */; };
F865B4CF2A024AD8008ACDFC /* StatusData+Faulty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865B4CC2A024AD8008ACDFC /* StatusData+Faulty.swift */; };
F865B4D12A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865B4D02A024AFE008ACDFC /* AttachmentData+Faulty.swift */; };
F865B4D22A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865B4D02A024AFE008ACDFC /* AttachmentData+Faulty.swift */; };
F865B4D32A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865B4D02A024AFE008ACDFC /* AttachmentData+Faulty.swift */; };
F866F6A0296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */; };
F866F6A1296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */; };
F866F6A1296040A8002E8F88 /* ApplicationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings.swift */; };
F866F6A329604161002E8F88 /* AccountDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A229604161002E8F88 /* AccountDataHandler.swift */; };
F866F6A529604194002E8F88 /* ApplicationSettingsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A429604194002E8F88 /* ApplicationSettingsHandler.swift */; };
F866F6A729604629002E8F88 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A629604629002E8F88 /* SignInView.swift */; };
@ -106,7 +76,6 @@
F8705A7B29FF872F00DA818A /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8705A7A29FF872F00DA818A /* QRCodeGenerator.swift */; };
F8705A7E29FF880600DA818A /* FileFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8705A7D29FF880600DA818A /* FileFetcher.swift */; };
F870EE5229F1645C00A2D43B /* MainNavigationOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F870EE5129F1645C00A2D43B /* MainNavigationOptions.swift */; };
F871F21D29EF0D7000A351EF /* NavigationMenuItemDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = F871F21C29EF0D7000A351EF /* NavigationMenuItemDetails.swift */; };
F8742FC429990AFB00E9642B /* ClientError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8742FC329990AFB00E9642B /* ClientError.swift */; };
F8764187298ABB520057D362 /* ViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8764186298ABB520057D362 /* ViewState.swift */; };
F876418D298AE5020057D362 /* PaginableStatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F876418C298AE5020057D362 /* PaginableStatusesView.swift */; };
@ -114,6 +83,7 @@
F87AEB922986C44E00434FB6 /* AuthorizationSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = F87AEB912986C44E00434FB6 /* AuthorizationSession.swift */; };
F87AEB972986D16D00434FB6 /* AuthorisationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F87AEB962986D16D00434FB6 /* AuthorisationError.swift */; };
F883402029B62AE900C3E096 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F883401F29B62AE900C3E096 /* SearchView.swift */; };
F886BBAC2AE7CF510083152B /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F886BBAB2AE7CF510083152B /* NotificationView.swift */; };
F88AB05329B3613900345EDE /* PhotoUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88AB05229B3613900345EDE /* PhotoUrl.swift */; };
F88AB05529B3626300345EDE /* ImageGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88AB05429B3626300345EDE /* ImageGrid.swift */; };
F88AB05829B36B8200345EDE /* AccountsPhotoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88AB05729B36B8200345EDE /* AccountsPhotoView.swift */; };
@ -123,53 +93,40 @@
F88BC51329E02FD800CE6141 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88BC51229E02FD800CE6141 /* ComposeView.swift */; };
F88BC51629E0307F00CE6141 /* NotificationsName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88BC51529E0307F00CE6141 /* NotificationsName.swift */; };
F88BC51B29E0350300CE6141 /* ClientKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC51A29E0350300CE6141 /* ClientKit */; };
F88BC51D29E0377B00CE6141 /* AccountData+AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88BC51C29E0377B00CE6141 /* AccountData+AccountModel.swift */; };
F88BC51F29E03ED300CE6141 /* ClientKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC51E29E03ED300CE6141 /* ClientKit */; };
F88BC52729E0431D00CE6141 /* ServicesKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC52629E0431D00CE6141 /* ServicesKit */; };
F88BC52A29E046D700CE6141 /* WidgetsKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC52929E046D700CE6141 /* WidgetsKit */; };
F88BC52D29E04BB600CE6141 /* EnvironmentKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC52C29E04BB600CE6141 /* EnvironmentKit */; };
F88BC52F29E04C5F00CE6141 /* EnvironmentKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC52E29E04C5F00CE6141 /* EnvironmentKit */; };
F88BC53029E0672000CE6141 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F835082629BEF9C400DE3247 /* Localizable.strings */; };
F88BC53229E0677000CE6141 /* EnvironmentKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC53129E0677000CE6141 /* EnvironmentKit */; };
F88BC53B29E06A5100CE6141 /* ImageContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88BC53A29E06A5100CE6141 /* ImageContextMenu.swift */; };
F88BC53D29E06EAD00CE6141 /* ServicesKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC53C29E06EAD00CE6141 /* ServicesKit */; };
F88BC53F29E06EB100CE6141 /* WidgetsKit in Frameworks */ = {isa = PBXBuildFile; productRef = F88BC53E29E06EB100CE6141 /* WidgetsKit */; };
F88BC54129E072A600CE6141 /* CoreDataError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F864F7A429BBA01D00B13921 /* CoreDataError.swift */; };
F88BC54229E072A900CE6141 /* AttachmentDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048092961EA1900E6868A /* AttachmentDataHandler.swift */; };
F88BC54329E072AC00CE6141 /* StatusDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048072961E6DE00E6868A /* StatusDataHandler.swift */; };
F88BC54429E072AF00CE6141 /* ApplicationSettingsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A429604194002E8F88 /* ApplicationSettingsHandler.swift */; };
F88BC54529E072B200CE6141 /* AccountDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A229604161002E8F88 /* AccountDataHandler.swift */; };
F88BC54629E072B500CE6141 /* CoreDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2474295C37BB0006098B /* CoreDataHandler.swift */; };
F88BC54729E072B800CE6141 /* AccountData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */; };
F88BC54829E072BC00CE6141 /* AccountData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */; };
F88BC54929E072C000CE6141 /* ApplicationSettings+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */; };
F88BC54A29E072C400CE6141 /* ApplicationSettings+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */; };
F88BC54B29E072CA00CE6141 /* StatusData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048022961850500E6868A /* StatusData+CoreDataProperties.swift */; };
F88BC54C29E072CD00CE6141 /* StatusData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048012961850500E6868A /* StatusData+CoreDataClass.swift */; };
F88BC54D29E072D600CE6141 /* AttachmentData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80048002961850500E6868A /* AttachmentData+CoreDataProperties.swift */; };
F88BC54E29E072D900CE6141 /* AttachmentData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80047FF2961850500E6868A /* AttachmentData+CoreDataClass.swift */; };
F88BC54F29E073BC00CE6141 /* AccountData+AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88BC51C29E0377B00CE6141 /* AccountData+AccountModel.swift */; };
F88BC55029E074EB00CE6141 /* Vernissage.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */; };
F88BC54629E072B500CE6141 /* SwiftDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2474295C37BB0006098B /* SwiftDataHandler.swift */; };
F88BC54729E072B800CE6141 /* AccountData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData.swift */; };
F88BC54929E072C000CE6141 /* ApplicationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings.swift */; };
F88BC55229E0798900CE6141 /* SharedAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F88BC55129E0798900CE6141 /* SharedAssets.xcassets */; };
F88BC55429E0798900CE6141 /* SharedAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F88BC55129E0798900CE6141 /* SharedAssets.xcassets */; };
F88C246C295C37B80006098B /* VernissageApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C246B295C37B80006098B /* VernissageApp.swift */; };
F88C246E295C37B80006098B /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C246D295C37B80006098B /* MainView.swift */; };
F88C2470295C37BB0006098B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F88C246F295C37BB0006098B /* Assets.xcassets */; };
F88C2473295C37BB0006098B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F88C2472295C37BB0006098B /* Preview Assets.xcassets */; };
F88C2475295C37BB0006098B /* CoreDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2474295C37BB0006098B /* CoreDataHandler.swift */; };
F88C2478295C37BB0006098B /* Vernissage.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */; };
F88C2475295C37BB0006098B /* SwiftDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2474295C37BB0006098B /* SwiftDataHandler.swift */; };
F88C2482295C3A4F0006098B /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88C2481295C3A4F0006098B /* StatusView.swift */; };
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D41297E69FD0057491A /* StatusesView.swift */; };
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D47297E90CD0057491A /* TrendStatusesView.swift */; };
F88E4D4A297EA0490057491A /* RouterPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D49297EA0490057491A /* RouterPath.swift */; };
F88E4D4D297EA4290057491A /* EmojiText in Frameworks */ = {isa = PBXBuildFile; productRef = F88E4D4C297EA4290057491A /* EmojiText */; };
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D55297EAD6E0057491A /* AppRouteur.swift */; };
F88FAD21295F3944009B20C9 /* HomeFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD20295F3944009B20C9 /* HomeFeedView.swift */; };
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD26295F400E009B20C9 /* NotificationsView.swift */; };
F88FAD2A295F43B8009B20C9 /* AccountData+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */; };
F88FAD2B295F43B8009B20C9 /* AccountData+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */; };
F891E7CE29C35BF50022C449 /* ImageRowItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F891E7CD29C35BF50022C449 /* ImageRowItem.swift */; };
F88FAD2B295F43B8009B20C9 /* AccountData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD29295F43B8009B20C9 /* AccountData.swift */; };
F891E7D029C368750022C449 /* ImageRowItemAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = F891E7CF29C368750022C449 /* ImageRowItemAsync.swift */; };
F89229EF2ADA63620040C964 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = F89229EE2ADA63620040C964 /* Localizable.xcstrings */; };
F89229F02ADA63620040C964 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = F89229EE2ADA63620040C964 /* Localizable.xcstrings */; };
F89229F12ADA63620040C964 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = F89229EE2ADA63620040C964 /* Localizable.xcstrings */; };
F897978F29684BCB00B22335 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F897978E29684BCB00B22335 /* LoadingView.swift */; };
F89992C9296D6DC7005994BF /* CommentBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89992C8296D6DC7005994BF /* CommentBodyView.swift */; };
F89A46DC296EAACE0062125F /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89A46DB296EAACE0062125F /* SettingsView.swift */; };
@ -177,7 +134,6 @@
F89AC00529A1F9B500F4159F /* AppMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89AC00429A1F9B500F4159F /* AppMetadata.swift */; };
F89B5CC029D019B600549F2F /* HTMLString in Frameworks */ = {isa = PBXBuildFile; productRef = F89B5CBF29D019B600549F2F /* HTMLString */; };
F89B5CC229D01BF700549F2F /* InstanceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89B5CC129D01BF700549F2F /* InstanceView.swift */; };
F89CEB802984198600A1376F /* AttachmentData+HighestImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89CEB7F2984198600A1376F /* AttachmentData+HighestImage.swift */; };
F89D6C4229717FDC001DA3D4 /* AccountsSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C4129717FDC001DA3D4 /* AccountsSectionView.swift */; };
F89D6C4429718092001DA3D4 /* AccentsSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C4329718092001DA3D4 /* AccentsSectionView.swift */; };
F89D6C4629718193001DA3D4 /* GeneralSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F89D6C4529718193001DA3D4 /* GeneralSectionView.swift */; };
@ -193,13 +149,28 @@
F8B0886029943498002AB40A /* OtherSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B0885F29943498002AB40A /* OtherSectionView.swift */; };
F8B08862299435C9002AB40A /* SupportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B08861299435C9002AB40A /* SupportView.swift */; };
F8B758DE2AB9DD85000C8068 /* ColumnData.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8B758DD2AB9DD85000C8068 /* ColumnData.swift */; };
F8D0E5222AE2A2630061C561 /* HomeTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D0E5212AE2A2630061C561 /* HomeTimelineView.swift */; };
F8D0E5242AE2A88A0061C561 /* HomeTimelineService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D0E5232AE2A88A0061C561 /* HomeTimelineService.swift */; };
F8D5444329D4066C002225D6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D5444229D4066C002225D6 /* AppDelegate.swift */; };
F8D8E0CB2ACC237000AA1374 /* ViewedStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D8E0CA2ACC237000AA1374 /* ViewedStatus.swift */; };
F8D8E0CC2ACC237000AA1374 /* ViewedStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D8E0CA2ACC237000AA1374 /* ViewedStatus.swift */; };
F8D8E0CD2ACC237000AA1374 /* ViewedStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D8E0CA2ACC237000AA1374 /* ViewedStatus.swift */; };
F8D8E0CF2ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D8E0CE2ACC23B300AA1374 /* ViewedStatusHandler.swift */; };
F8D8E0D02ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D8E0CE2ACC23B300AA1374 /* ViewedStatusHandler.swift */; };
F8D8E0D12ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8D8E0CE2ACC23B300AA1374 /* ViewedStatusHandler.swift */; };
F8DE749F2AE4F7B500ACD188 /* NotificationsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DE749E2AE4F7B500ACD188 /* NotificationsService.swift */; };
F8DF38E429DD68820047F1AA /* ViewOffsetKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF38E329DD68820047F1AA /* ViewOffsetKey.swift */; };
F8DF38E629DDB98A0047F1AA /* SocialsSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8DF38E529DDB98A0047F1AA /* SocialsSectionView.swift */; };
F8E023642B3C1EBD004F7E18 /* View+If.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E023632B3C1EBD004F7E18 /* View+If.swift */; };
F8E36E462AB8745300769C55 /* Sizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E36E452AB8745300769C55 /* Sizable.swift */; };
F8E36E482AB874A500769C55 /* StatusModel+Sizeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E36E472AB874A500769C55 /* StatusModel+Sizeable.swift */; };
F8E6D03329CDD52500416CCA /* EditProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E6D03229CDD52500416CCA /* EditProfileView.swift */; };
F8F6E44229BC58F20004795E /* Vernissage.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */; };
F8E7ADFE2AD44CEB0038FFFD /* AccountRelationship.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship.swift */; };
F8E7ADFF2AD44CEB0038FFFD /* AccountRelationship.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship.swift */; };
F8E7AE002AD44CEB0038FFFD /* AccountRelationship.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship.swift */; };
F8E7AE022AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */; };
F8E7AE032AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */; };
F8E7AE042AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */; };
F8F6E44C29BCC1F70004795E /* PhotoSmallWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44629BCC0DC0004795E /* PhotoSmallWidgetView.swift */; };
F8F6E44D29BCC1F90004795E /* PhotoMediumWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44829BCC0F00004795E /* PhotoMediumWidgetView.swift */; };
F8F6E44E29BCC1FB0004795E /* PhotoLargeWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44A29BCC0FF0004795E /* PhotoLargeWidgetView.swift */; };
@ -241,26 +212,15 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
F80047FF2961850500E6868A /* AttachmentData+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+CoreDataClass.swift"; sourceTree = "<group>"; };
F80048002961850500E6868A /* AttachmentData+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+CoreDataProperties.swift"; sourceTree = "<group>"; };
F80048012961850500E6868A /* StatusData+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+CoreDataClass.swift"; sourceTree = "<group>"; };
F80048022961850500E6868A /* StatusData+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+CoreDataProperties.swift"; sourceTree = "<group>"; };
F80048072961E6DE00E6868A /* StatusDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusDataHandler.swift; sourceTree = "<group>"; };
F80048092961EA1900E6868A /* AttachmentDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentDataHandler.swift; sourceTree = "<group>"; };
F802884E297AEED5000BDD51 /* DatabaseError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseError.swift; sourceTree = "<group>"; };
F805DCF029DBEF83006A1FD9 /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
F808641329756666009F035C /* NotificationRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRowView.swift; sourceTree = "<group>"; };
F8121CA7298A86D600B466C7 /* InstanceRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceRowView.swift; sourceTree = "<group>"; };
F815F60B29E49CF20044566B /* Avatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Avatar.swift; sourceTree = "<group>"; };
F8206A032A06547600E19412 /* Vernissage-014.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-014.xcdatamodel"; sourceTree = "<group>"; };
F8210DCE2966B600001D9973 /* ImageRowAsync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowAsync.swift; sourceTree = "<group>"; };
F8210DDC2966CF17001D9973 /* StatusData+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+Status.swift"; sourceTree = "<group>"; };
F8210DDE2966CFC7001D9973 /* AttachmentData+Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+Attachment.swift"; sourceTree = "<group>"; };
F8210DE92966E4F9001D9973 /* AnimatePlaceholderModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatePlaceholderModifier.swift; sourceTree = "<group>"; };
F825F0C829F7A562008BD204 /* UserProfilePrivateAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfilePrivateAccountView.swift; sourceTree = "<group>"; };
F825F0CA29F7CFC4008BD204 /* FollowRequestsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowRequestsView.swift; sourceTree = "<group>"; };
F835082529BEF9C400DE3247 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
F835082729BEFA1E00DE3247 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
F837269429A221420098D3C4 /* PixelfedKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PixelfedKit; sourceTree = "<group>"; };
F83CBEFA298298A1002972C8 /* ImageCarouselPicture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCarouselPicture.swift; sourceTree = "<group>"; };
F844F42429D2DC39000DD896 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
@ -271,16 +231,11 @@
F84625F329FE2BF9002D3AF4 /* QRCodeProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeProvider.swift; sourceTree = "<group>"; };
F84625F729FE2C2F002D3AF4 /* AccountFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountFetcher.swift; sourceTree = "<group>"; };
F858906A29E1CC7A00D4BDED /* UIApplication+Window.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+Window.swift"; sourceTree = "<group>"; };
F85B586C29ED169B00A16D12 /* Vernissage-010.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-010.xcdatamodel"; sourceTree = "<group>"; };
F85D0C642ABA08F9002B3577 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
F85D4970296402DC00751DF7 /* AuthorizationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationService.swift; sourceTree = "<group>"; };
F85D4974296407F100751DF7 /* HomeTimelineService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineService.swift; sourceTree = "<group>"; };
F85D497629640A5200751DF7 /* ImageRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRow.swift; sourceTree = "<group>"; };
F85D497829640B9D00751DF7 /* ImagesCarousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesCarousel.swift; sourceTree = "<group>"; };
F85D497C29640D5900751DF7 /* InteractionRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionRow.swift; sourceTree = "<group>"; };
F85D497E296416C800751DF7 /* CommentsSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentsSectionView.swift; sourceTree = "<group>"; };
F85D498229642FAC00751DF7 /* AttachmentData+Comperable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+Comperable.swift"; sourceTree = "<group>"; };
F85D49842964301800751DF7 /* StatusData+Attachments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+Attachments.swift"; sourceTree = "<group>"; };
F85D4DFD29B78C8400345267 /* HashtagModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagModel.swift; sourceTree = "<group>"; };
F85DBF8E296732E20069BF89 /* AccountsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsView.swift; sourceTree = "<group>"; };
F86167C5297FE6CC004D1F67 /* AvatarShapesSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarShapesSectionView.swift; sourceTree = "<group>"; };
@ -296,11 +251,7 @@
F864F77729BB930000B13921 /* PhotoWidgetEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoWidgetEntry.swift; sourceTree = "<group>"; };
F864F77B29BB982100B13921 /* StatusFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusFetcher.swift; sourceTree = "<group>"; };
F864F7A429BBA01D00B13921 /* CoreDataError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataError.swift; sourceTree = "<group>"; };
F865B4CC2A024AD8008ACDFC /* StatusData+Faulty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusData+Faulty.swift"; sourceTree = "<group>"; };
F865B4D02A024AFE008ACDFC /* AttachmentData+Faulty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+Faulty.swift"; sourceTree = "<group>"; };
F865B4D42A0252FB008ACDFC /* Vernissage-013.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-013.xcdatamodel"; sourceTree = "<group>"; };
F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ApplicationSettings+CoreDataClass.swift"; sourceTree = "<group>"; };
F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ApplicationSettings+CoreDataProperties.swift"; sourceTree = "<group>"; };
F866F69F296040A8002E8F88 /* ApplicationSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationSettings.swift; sourceTree = "<group>"; };
F866F6A229604161002E8F88 /* AccountDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDataHandler.swift; sourceTree = "<group>"; };
F866F6A429604194002E8F88 /* ApplicationSettingsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationSettingsHandler.swift; sourceTree = "<group>"; };
F866F6A629604629002E8F88 /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
@ -324,8 +275,6 @@
F8705A7A29FF872F00DA818A /* QRCodeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeGenerator.swift; sourceTree = "<group>"; };
F8705A7D29FF880600DA818A /* FileFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileFetcher.swift; sourceTree = "<group>"; };
F870EE5129F1645C00A2D43B /* MainNavigationOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationOptions.swift; sourceTree = "<group>"; };
F871F21C29EF0D7000A351EF /* NavigationMenuItemDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMenuItemDetails.swift; sourceTree = "<group>"; };
F871F21F29EF0FEC00A351EF /* Vernissage-011.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-011.xcdatamodel"; sourceTree = "<group>"; };
F8742FC329990AFB00E9642B /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = "<group>"; };
F8764186298ABB520057D362 /* ViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewState.swift; sourceTree = "<group>"; };
F876418C298AE5020057D362 /* PaginableStatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginableStatusesView.swift; sourceTree = "<group>"; };
@ -333,6 +282,7 @@
F87AEB912986C44E00434FB6 /* AuthorizationSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationSession.swift; sourceTree = "<group>"; };
F87AEB962986D16D00434FB6 /* AuthorisationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorisationError.swift; sourceTree = "<group>"; };
F883401F29B62AE900C3E096 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
F886BBAB2AE7CF510083152B /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = "<group>"; };
F88AB05229B3613900345EDE /* PhotoUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoUrl.swift; sourceTree = "<group>"; };
F88AB05429B3626300345EDE /* ImageGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGrid.swift; sourceTree = "<group>"; };
F88AB05729B36B8200345EDE /* AccountsPhotoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsPhotoView.swift; sourceTree = "<group>"; };
@ -345,7 +295,6 @@
F88BC51429E02FEB00CE6141 /* VernissageShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = VernissageShareExtension.entitlements; sourceTree = "<group>"; };
F88BC51529E0307F00CE6141 /* NotificationsName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsName.swift; sourceTree = "<group>"; };
F88BC51929E0344000CE6141 /* ClientKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = ClientKit; sourceTree = "<group>"; };
F88BC51C29E0377B00CE6141 /* AccountData+AccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+AccountModel.swift"; sourceTree = "<group>"; };
F88BC52529E0421F00CE6141 /* ServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = ServicesKit; sourceTree = "<group>"; };
F88BC52829E0467400CE6141 /* WidgetsKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = WidgetsKit; sourceTree = "<group>"; };
F88BC52B29E04AC200CE6141 /* EnvironmentKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = EnvironmentKit; sourceTree = "<group>"; };
@ -356,41 +305,31 @@
F88C246D295C37B80006098B /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
F88C246F295C37BB0006098B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
F88C2472295C37BB0006098B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
F88C2474295C37BB0006098B /* CoreDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataHandler.swift; sourceTree = "<group>"; };
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Vernissage.xcdatamodel; sourceTree = "<group>"; };
F88C2474295C37BB0006098B /* SwiftDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDataHandler.swift; sourceTree = "<group>"; };
F88C2481295C3A4F0006098B /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
F88E4D41297E69FD0057491A /* StatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusesView.swift; sourceTree = "<group>"; };
F88E4D47297E90CD0057491A /* TrendStatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendStatusesView.swift; sourceTree = "<group>"; };
F88E4D49297EA0490057491A /* RouterPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterPath.swift; sourceTree = "<group>"; };
F88E4D55297EAD6E0057491A /* AppRouteur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteur.swift; sourceTree = "<group>"; };
F88FAD20295F3944009B20C9 /* HomeFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeFeedView.swift; sourceTree = "<group>"; };
F88FAD26295F400E009B20C9 /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+CoreDataClass.swift"; sourceTree = "<group>"; };
F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountData+CoreDataProperties.swift"; sourceTree = "<group>"; };
F8911A1829DE9E5500770F44 /* Vernissage-007.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-007.xcdatamodel"; sourceTree = "<group>"; };
F891E7CD29C35BF50022C449 /* ImageRowItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowItem.swift; sourceTree = "<group>"; };
F88FAD29295F43B8009B20C9 /* AccountData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountData.swift; sourceTree = "<group>"; };
F891E7CF29C368750022C449 /* ImageRowItemAsync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRowItemAsync.swift; sourceTree = "<group>"; };
F89229EE2ADA63620040C964 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
F897978E29684BCB00B22335 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
F89992C8296D6DC7005994BF /* CommentBodyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentBodyView.swift; sourceTree = "<group>"; };
F89A46DB296EAACE0062125F /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
F89A46DD296EABA20062125F /* StatusPlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusPlaceholderView.swift; sourceTree = "<group>"; };
F89AC00429A1F9B500F4159F /* AppMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMetadata.swift; sourceTree = "<group>"; };
F89B5CC129D01BF700549F2F /* InstanceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceView.swift; sourceTree = "<group>"; };
F89CEB7F2984198600A1376F /* AttachmentData+HighestImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttachmentData+HighestImage.swift"; sourceTree = "<group>"; };
F89D6C4129717FDC001DA3D4 /* AccountsSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSectionView.swift; sourceTree = "<group>"; };
F89D6C4329718092001DA3D4 /* AccentsSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccentsSectionView.swift; sourceTree = "<group>"; };
F89D6C4529718193001DA3D4 /* GeneralSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSectionView.swift; sourceTree = "<group>"; };
F89D6C49297196FF001DA3D4 /* ImageViewer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewer.swift; sourceTree = "<group>"; };
F89F0605299139F6003DC875 /* Vernissage-002.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-002.xcdatamodel"; sourceTree = "<group>"; };
F89F57AF29D1C11200001EE3 /* RelationshipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipModel.swift; sourceTree = "<group>"; };
F8A270DA29F500860062D275 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
F8A4A88429E4099900267E36 /* Vernissage-008.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-008.xcdatamodel"; sourceTree = "<group>"; };
F8A93D7D2965FD89001D8331 /* UserProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileView.swift; sourceTree = "<group>"; };
F8AFF7C029B259150087D083 /* HashtagsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagsView.swift; sourceTree = "<group>"; };
F8AFF7C329B25EF40087D083 /* ImagesGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesGrid.swift; sourceTree = "<group>"; };
F8B05AC929B488C600857221 /* Vernissage-003.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-003.xcdatamodel"; sourceTree = "<group>"; };
F8B05ACA29B489B100857221 /* HapticsSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticsSectionView.swift; sourceTree = "<group>"; };
F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-004.xcdatamodel"; sourceTree = "<group>"; };
F8B05ACD29B48E2F00857221 /* MediaSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaSettingsView.swift; sourceTree = "<group>"; };
F8B0885D29942E31002AB40A /* ThirdPartyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartyView.swift; sourceTree = "<group>"; };
F8B0885F29943498002AB40A /* OtherSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherSectionView.swift; sourceTree = "<group>"; };
@ -398,17 +337,20 @@
F8B3699A29D86EB600BE3808 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = "<group>"; };
F8B3699B29D86EBD00BE3808 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = "<group>"; };
F8B758DD2AB9DD85000C8068 /* ColumnData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColumnData.swift; sourceTree = "<group>"; };
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-001.xcdatamodel"; sourceTree = "<group>"; };
F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-005.xcdatamodel"; sourceTree = "<group>"; };
F8D0E5212AE2A2630061C561 /* HomeTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineView.swift; sourceTree = "<group>"; };
F8D0E5232AE2A88A0061C561 /* HomeTimelineService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineService.swift; sourceTree = "<group>"; };
F8D5444229D4066C002225D6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F8D8E0CA2ACC237000AA1374 /* ViewedStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewedStatus.swift; sourceTree = "<group>"; };
F8D8E0CE2ACC23B300AA1374 /* ViewedStatusHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewedStatusHandler.swift; sourceTree = "<group>"; };
F8DE749E2AE4F7B500ACD188 /* NotificationsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsService.swift; sourceTree = "<group>"; };
F8DF38E329DD68820047F1AA /* ViewOffsetKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewOffsetKey.swift; sourceTree = "<group>"; };
F8DF38E529DDB98A0047F1AA /* SocialsSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialsSectionView.swift; sourceTree = "<group>"; };
F8DF38E729DDC3D20047F1AA /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Localizable.strings; sourceTree = "<group>"; };
F8E023632B3C1EBD004F7E18 /* View+If.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+If.swift"; sourceTree = "<group>"; };
F8E36E452AB8745300769C55 /* Sizable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sizable.swift; sourceTree = "<group>"; };
F8E36E472AB874A500769C55 /* StatusModel+Sizeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusModel+Sizeable.swift"; sourceTree = "<group>"; };
F8E6D03229CDD52500416CCA /* EditProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfileView.swift; sourceTree = "<group>"; };
F8EF371429C624DA00669F45 /* Vernissage-006.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-006.xcdatamodel"; sourceTree = "<group>"; };
F8EF3C8B29FC3A5F00CBFF7C /* Vernissage-012.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-012.xcdatamodel"; sourceTree = "<group>"; };
F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRelationship.swift; sourceTree = "<group>"; };
F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRelationshipHandler.swift; sourceTree = "<group>"; };
F8F6E44329BC5CAA0004795E /* VernissageWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = VernissageWidgetExtension.entitlements; sourceTree = "<group>"; };
F8F6E44429BC5CC50004795E /* Vernissage.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Vernissage.entitlements; sourceTree = "<group>"; };
F8F6E44629BCC0DC0004795E /* PhotoSmallWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoSmallWidgetView.swift; sourceTree = "<group>"; };
@ -417,7 +359,6 @@
F8F6E45029BCE9190004795E /* UIImage+Resize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Resize.swift"; sourceTree = "<group>"; };
F8FAA0AC2AB0BCB400FD78BD /* View+ContainerBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ContainerBackground.swift"; sourceTree = "<group>"; };
F8FB8AB929EB2ED400342C04 /* NavigationMenuButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMenuButtons.swift; sourceTree = "<group>"; };
F8FFBD4929E99BEE0047EE80 /* Vernissage-009.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-009.xcdatamodel"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -425,7 +366,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F84625FB29FE393B002D3AF4 /* QRCode in Frameworks */,
F864F76129BB91B400B13921 /* SwiftUI.framework in Frameworks */,
F864F77A29BB94A800B13921 /* PixelfedKit in Frameworks */,
F864F75F29BB91B400B13921 /* WidgetKit.framework in Frameworks */,
@ -512,7 +452,7 @@
F89D6C4829718868001DA3D4 /* StatusView */,
F88C246D295C37B80006098B /* MainView.swift */,
F88ABD9329687CA4004EF61E /* ComposeView.swift */,
F88FAD20295F3944009B20C9 /* HomeFeedView.swift */,
F8D0E5212AE2A2630061C561 /* HomeTimelineView.swift */,
F88AB05729B36B8200345EDE /* AccountsPhotoView.swift */,
F88E4D47297E90CD0057491A /* TrendStatusesView.swift */,
F883401F29B62AE900C3E096 /* SearchView.swift */,
@ -541,7 +481,6 @@
F85D4DFD29B78C8400345267 /* HashtagModel.swift */,
F89F57AF29D1C11200001EE3 /* RelationshipModel.swift */,
F8DF38E329DD68820047F1AA /* ViewOffsetKey.swift */,
F871F21C29EF0D7000A351EF /* NavigationMenuItemDetails.swift */,
F8624D3C29F2D3AC00204986 /* SelectedMenuItemDetails.swift */,
F8E36E452AB8745300769C55 /* Sizable.swift */,
F8B758DD2AB9DD85000C8068 /* ColumnData.swift */,
@ -552,28 +491,15 @@
F8341F96295C6427009C8EE6 /* CoreData */ = {
isa = PBXGroup;
children = (
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */,
F80047FF2961850500E6868A /* AttachmentData+CoreDataClass.swift */,
F80048002961850500E6868A /* AttachmentData+CoreDataProperties.swift */,
F85D498229642FAC00751DF7 /* AttachmentData+Comperable.swift */,
F8210DDE2966CFC7001D9973 /* AttachmentData+Attachment.swift */,
F89CEB7F2984198600A1376F /* AttachmentData+HighestImage.swift */,
F865B4D02A024AFE008ACDFC /* AttachmentData+Faulty.swift */,
F80048012961850500E6868A /* StatusData+CoreDataClass.swift */,
F80048022961850500E6868A /* StatusData+CoreDataProperties.swift */,
F85D49842964301800751DF7 /* StatusData+Attachments.swift */,
F8210DDC2966CF17001D9973 /* StatusData+Status.swift */,
F865B4CC2A024AD8008ACDFC /* StatusData+Faulty.swift */,
F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */,
F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */,
F88FAD28295F43B8009B20C9 /* AccountData+CoreDataClass.swift */,
F88FAD29295F43B8009B20C9 /* AccountData+CoreDataProperties.swift */,
F88BC51C29E0377B00CE6141 /* AccountData+AccountModel.swift */,
F88C2474295C37BB0006098B /* CoreDataHandler.swift */,
F866F69F296040A8002E8F88 /* ApplicationSettings.swift */,
F88FAD29295F43B8009B20C9 /* AccountData.swift */,
F8D8E0CA2ACC237000AA1374 /* ViewedStatus.swift */,
F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship.swift */,
F88C2474295C37BB0006098B /* SwiftDataHandler.swift */,
F866F6A229604161002E8F88 /* AccountDataHandler.swift */,
F866F6A429604194002E8F88 /* ApplicationSettingsHandler.swift */,
F80048072961E6DE00E6868A /* StatusDataHandler.swift */,
F80048092961EA1900E6868A /* AttachmentDataHandler.swift */,
F8D8E0CE2ACC23B300AA1374 /* ViewedStatusHandler.swift */,
F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */,
F864F7A429BBA01D00B13921 /* CoreDataError.swift */,
);
path = CoreData;
@ -582,7 +508,7 @@
F835081F29BEF88600DE3247 /* Localization */ = {
isa = PBXGroup;
children = (
F835082629BEF9C400DE3247 /* Localizable.strings */,
F89229EE2ADA63620040C964 /* Localizable.xcstrings */,
);
path = Localization;
sourceTree = "<group>";
@ -590,8 +516,6 @@
F83901A2295D863B00456AE2 /* Widgets */ = {
isa = PBXGroup;
children = (
F85D497629640A5200751DF7 /* ImageRow.swift */,
F891E7CD29C35BF50022C449 /* ImageRowItem.swift */,
F8210DCE2966B600001D9973 /* ImageRowAsync.swift */,
F891E7CF29C368750022C449 /* ImageRowItemAsync.swift */,
F85D497829640B9D00751DF7 /* ImagesCarousel.swift */,
@ -712,6 +636,7 @@
F8B05ACA29B489B100857221 /* HapticsSectionView.swift */,
F8B05ACD29B48E2F00857221 /* MediaSettingsView.swift */,
F8DF38E529DDB98A0047F1AA /* SocialsSectionView.swift */,
F886BBAB2AE7CF510083152B /* NotificationView.swift */,
);
path = Subviews;
sourceTree = "<group>";
@ -786,7 +711,6 @@
F844F42429D2DC39000DD896 /* LICENSE */,
F8B3699A29D86EB600BE3808 /* .swiftlint.yml */,
F8B3699B29D86EBD00BE3808 /* .gitignore */,
F8CB3DF029D80B1E00CDAE5A /* Resources */,
F835081F29BEF88600DE3247 /* Localization */,
F8341F96295C6427009C8EE6 /* CoreData */,
F88C246A295C37B80006098B /* Vernissage */,
@ -847,10 +771,11 @@
children = (
F85D4970296402DC00751DF7 /* AuthorizationService.swift */,
F87AEB912986C44E00434FB6 /* AuthorizationSession.swift */,
F85D4974296407F100751DF7 /* HomeTimelineService.swift */,
F88E4D49297EA0490057491A /* RouterPath.swift */,
F878842129A4A4E3003CFAD2 /* AppMetadataService.swift */,
F86BC9E829EBBB66009415EC /* ImageSaver.swift */,
F8D0E5232AE2A88A0061C561 /* HomeTimelineService.swift */,
F8DE749E2AE4F7B500ACD188 /* NotificationsService.swift */,
);
path = Services;
sourceTree = "<group>";
@ -900,13 +825,6 @@
path = EnvironmentObjects;
sourceTree = "<group>";
};
F8CB3DF029D80B1E00CDAE5A /* Resources */ = {
isa = PBXGroup;
children = (
);
path = Resources;
sourceTree = "<group>";
};
F8F6E44529BCC0C90004795E /* Views */ = {
isa = PBXGroup;
children = (
@ -923,6 +841,7 @@
F815F60B29E49CF20044566B /* Avatar.swift */,
F8F6E45029BCE9190004795E /* UIImage+Resize.swift */,
F8FAA0AC2AB0BCB400FD78BD /* View+ContainerBackground.swift */,
F8E023632B3C1EBD004F7E18 /* View+If.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -946,7 +865,6 @@
packageProductDependencies = (
F864F77929BB94A800B13921 /* PixelfedKit */,
F88BC52E29E04C5F00CE6141 /* EnvironmentKit */,
F84625FA29FE393B002D3AF4 /* QRCode */,
);
productName = VernissageWidgetExtension;
productReference = F864F75D29BB91B400B13921 /* VernissageWidgetExtension.appex */;
@ -1038,13 +956,14 @@
pl,
eu,
fr,
es,
de,
);
mainGroup = F88C245F295C37B80006098B;
packageReferences = (
F8210DD32966BB7E001D9973 /* XCRemoteSwiftPackageReference "Nuke" */,
F88E4D4B297EA4290057491A /* XCRemoteSwiftPackageReference "EmojiText" */,
F89B5CBE29D019B600549F2F /* XCRemoteSwiftPackageReference "HTMLString" */,
F84625F929FE393B002D3AF4 /* XCRemoteSwiftPackageReference "QRCode" */,
F8A1920E2ABB322E00C2599A /* XCRemoteSwiftPackageReference "Semaphore" */,
);
productRefGroup = F88C2469295C37B80006098B /* Products */;
@ -1064,7 +983,7 @@
buildActionMask = 2147483647;
files = (
F85D0C652ABA08F9002B3577 /* Assets.xcassets in Resources */,
F835082429BEF9C400DE3247 /* Localizable.strings in Resources */,
F89229F02ADA63620040C964 /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1072,8 +991,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F88BC53029E0672000CE6141 /* Localizable.strings in Resources */,
F88BC55429E0798900CE6141 /* SharedAssets.xcassets in Resources */,
F89229F12ADA63620040C964 /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1083,7 +1002,7 @@
files = (
F88BC55229E0798900CE6141 /* SharedAssets.xcassets in Resources */,
F88C2473295C37BB0006098B /* Preview Assets.xcassets in Resources */,
F835082329BEF9C400DE3247 /* Localizable.strings in Resources */,
F89229EF2ADA63620040C964 /* Localizable.xcstrings in Resources */,
F88C2470295C37BB0006098B /* Assets.xcassets in Resources */,
F86A42FF299A8C5500DF7645 /* InAppPurchaseStoreKitConfiguration.storekit in Resources */,
);
@ -1098,42 +1017,36 @@
files = (
F864F77829BB930000B13921 /* PhotoWidgetEntry.swift in Sources */,
F864F77529BB92CE00B13921 /* PhotoProvider.swift in Sources */,
F8D8E0D02ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */,
F864F77629BB92CE00B13921 /* PhotoWidgetEntryView.swift in Sources */,
F8705A7729FF7ABD00DA818A /* QRCodeSmallWidgetView.swift in Sources */,
F864F77C29BB982100B13921 /* StatusFetcher.swift in Sources */,
F84625ED29FE295B002D3AF4 /* QRCodeLargeWidgetView.swift in Sources */,
F8F6E44229BC58F20004795E /* Vernissage.xcdatamodeld in Sources */,
F8F6E44C29BCC1F70004795E /* PhotoSmallWidgetView.swift in Sources */,
F864F76629BB91B400B13921 /* PhotoWidget.swift in Sources */,
F8F6E44D29BCC1F90004795E /* PhotoMediumWidgetView.swift in Sources */,
F815F60C29E49CF20044566B /* Avatar.swift in Sources */,
F8F6E44E29BCC1FB0004795E /* PhotoLargeWidgetView.swift in Sources */,
F864F76429BB91B400B13921 /* VernissageWidgetBundle.swift in Sources */,
F864F77D29BB9A4600B13921 /* AttachmentData+CoreDataClass.swift in Sources */,
F8E7ADFF2AD44CEB0038FFFD /* AccountRelationship.swift in Sources */,
F8D8E0CC2ACC237000AA1374 /* ViewedStatus.swift in Sources */,
F8E023642B3C1EBD004F7E18 /* View+If.swift in Sources */,
F864F7A629BBA01D00B13921 /* CoreDataError.swift in Sources */,
F864F77E29BB9A4900B13921 /* AttachmentData+CoreDataProperties.swift in Sources */,
F864F78229BB9A6500B13921 /* StatusData+CoreDataClass.swift in Sources */,
F864F78329BB9A6800B13921 /* StatusData+CoreDataProperties.swift in Sources */,
F864F78429BB9A6E00B13921 /* ApplicationSettings+CoreDataClass.swift in Sources */,
F8FAA0AD2AB0BCB400FD78BD /* View+ContainerBackground.swift in Sources */,
F864F78629BB9A7400B13921 /* AccountData+CoreDataClass.swift in Sources */,
F8705A7B29FF872F00DA818A /* QRCodeGenerator.swift in Sources */,
F865B4CE2A024AD8008ACDFC /* StatusData+Faulty.swift in Sources */,
F8705A7E29FF880600DA818A /* FileFetcher.swift in Sources */,
F865B4D22A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */,
F864F78529BB9A7100B13921 /* ApplicationSettings+CoreDataProperties.swift in Sources */,
F864F78529BB9A7100B13921 /* ApplicationSettings.swift in Sources */,
F84625E929FE2788002D3AF4 /* QRCodeWidget.swift in Sources */,
F864F78729BB9A7700B13921 /* AccountData+CoreDataProperties.swift in Sources */,
F864F78829BB9A7B00B13921 /* CoreDataHandler.swift in Sources */,
F864F78729BB9A7700B13921 /* AccountData.swift in Sources */,
F8E7AE032AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */,
F864F78829BB9A7B00B13921 /* SwiftDataHandler.swift in Sources */,
F8F6E45129BCE9190004795E /* UIImage+Resize.swift in Sources */,
F864F78929BB9A7D00B13921 /* AccountDataHandler.swift in Sources */,
F864F78A29BB9A8000B13921 /* ApplicationSettingsHandler.swift in Sources */,
F84625F229FE2B6B002D3AF4 /* QRCodeWidgetEntry.swift in Sources */,
F84625EB29FE28D4002D3AF4 /* QRCodeWidgetEntryView.swift in Sources */,
F864F78C29BB9A8500B13921 /* AttachmentDataHandler.swift in Sources */,
F84625F829FE2C2F002D3AF4 /* AccountFetcher.swift in Sources */,
F84625F429FE2BF9002D3AF4 /* QRCodeProvider.swift in Sources */,
F864F78B29BB9A8300B13921 /* StatusDataHandler.swift in Sources */,
F8705A7929FF7CCB00DA818A /* QRCodeMediumWidgetView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1143,26 +1056,18 @@
buildActionMask = 2147483647;
files = (
F88BC54529E072B200CE6141 /* AccountDataHandler.swift in Sources */,
F88BC54729E072B800CE6141 /* AccountData+CoreDataProperties.swift in Sources */,
F88BC54D29E072D600CE6141 /* AttachmentData+CoreDataProperties.swift in Sources */,
F88BC54F29E073BC00CE6141 /* AccountData+AccountModel.swift in Sources */,
F865B4D32A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */,
F88BC54629E072B500CE6141 /* CoreDataHandler.swift in Sources */,
F88BC54729E072B800CE6141 /* AccountData.swift in Sources */,
F8D8E0D12ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */,
F8E7AE002AD44CEB0038FFFD /* AccountRelationship.swift in Sources */,
F88BC54629E072B500CE6141 /* SwiftDataHandler.swift in Sources */,
F88BC50529E02F3900CE6141 /* ShareViewController.swift in Sources */,
F88BC54129E072A600CE6141 /* CoreDataError.swift in Sources */,
F88BC54229E072A900CE6141 /* AttachmentDataHandler.swift in Sources */,
F88BC54429E072AF00CE6141 /* ApplicationSettingsHandler.swift in Sources */,
F8D8E0CD2ACC237000AA1374 /* ViewedStatus.swift in Sources */,
F88BC51629E0307F00CE6141 /* NotificationsName.swift in Sources */,
F88BC54829E072BC00CE6141 /* AccountData+CoreDataClass.swift in Sources */,
F8E7AE042AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */,
F88BC51329E02FD800CE6141 /* ComposeView.swift in Sources */,
F88BC54E29E072D900CE6141 /* AttachmentData+CoreDataClass.swift in Sources */,
F88BC54C29E072CD00CE6141 /* StatusData+CoreDataClass.swift in Sources */,
F88BC54B29E072CA00CE6141 /* StatusData+CoreDataProperties.swift in Sources */,
F88BC54A29E072C400CE6141 /* ApplicationSettings+CoreDataClass.swift in Sources */,
F865B4CF2A024AD8008ACDFC /* StatusData+Faulty.swift in Sources */,
F88BC54929E072C000CE6141 /* ApplicationSettings+CoreDataProperties.swift in Sources */,
F88BC55029E074EB00CE6141 /* Vernissage.xcdatamodeld in Sources */,
F88BC54329E072AC00CE6141 /* StatusDataHandler.swift in Sources */,
F88BC54929E072C000CE6141 /* ApplicationSettings.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1170,60 +1075,44 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F85D497729640A5200751DF7 /* ImageRow.swift in Sources */,
F8210DDF2966CFC7001D9973 /* AttachmentData+Attachment.swift in Sources */,
F88AB05529B3626300345EDE /* ImageGrid.swift in Sources */,
F87AEB922986C44E00434FB6 /* AuthorizationSession.swift in Sources */,
F86A4301299A97F500DF7645 /* ProductIdentifiers.swift in Sources */,
F89D6C4229717FDC001DA3D4 /* AccountsSectionView.swift in Sources */,
F8E36E482AB874A500769C55 /* StatusModel+Sizeable.swift in Sources */,
F80048082961E6DE00E6868A /* StatusDataHandler.swift in Sources */,
F866F6A0296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift in Sources */,
F8210DEA2966E4F9001D9973 /* AnimatePlaceholderModifier.swift in Sources */,
F865B4D12A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */,
F8B08862299435C9002AB40A /* SupportView.swift in Sources */,
F8B05ACB29B489B100857221 /* HapticsSectionView.swift in Sources */,
F88FAD2B295F43B8009B20C9 /* AccountData+CoreDataProperties.swift in Sources */,
F85D4975296407F100751DF7 /* HomeTimelineService.swift in Sources */,
F80048062961850500E6868A /* StatusData+CoreDataProperties.swift in Sources */,
F88FAD21295F3944009B20C9 /* HomeFeedView.swift in Sources */,
F88C2475295C37BB0006098B /* CoreDataHandler.swift in Sources */,
F88FAD2B295F43B8009B20C9 /* AccountData.swift in Sources */,
F88C2475295C37BB0006098B /* SwiftDataHandler.swift in Sources */,
F87AEB972986D16D00434FB6 /* AuthorisationError.swift in Sources */,
F8742FC429990AFB00E9642B /* ClientError.swift in Sources */,
F883402029B62AE900C3E096 /* SearchView.swift in Sources */,
F88FAD2A295F43B8009B20C9 /* AccountData+CoreDataClass.swift in Sources */,
F871F21D29EF0D7000A351EF /* NavigationMenuItemDetails.swift in Sources */,
F8E36E462AB8745300769C55 /* Sizable.swift in Sources */,
F85DBF8F296732E20069BF89 /* AccountsView.swift in Sources */,
F805DCF129DBEF83006A1FD9 /* ReportView.swift in Sources */,
F8B0886029943498002AB40A /* OtherSectionView.swift in Sources */,
F808641429756666009F035C /* NotificationRowView.swift in Sources */,
F8624D3D29F2D3AC00204986 /* SelectedMenuItemDetails.swift in Sources */,
F8210DDD2966CF17001D9973 /* StatusData+Status.swift in Sources */,
F8210DCF2966B600001D9973 /* ImageRowAsync.swift in Sources */,
F85D498329642FAC00751DF7 /* AttachmentData+Comperable.swift in Sources */,
F86A4305299AA12800DF7645 /* PurchaseError.swift in Sources */,
F8B05ACE29B48E2F00857221 /* MediaSettingsView.swift in Sources */,
F89D6C4429718092001DA3D4 /* AccentsSectionView.swift in Sources */,
F88E4D42297E69FD0057491A /* StatusesView.swift in Sources */,
F878842229A4A4E3003CFAD2 /* AppMetadataService.swift in Sources */,
F85D497929640B9D00751DF7 /* ImagesCarousel.swift in Sources */,
F8D0E5222AE2A2630061C561 /* HomeTimelineView.swift in Sources */,
F89AC00529A1F9B500F4159F /* AppMetadata.swift in Sources */,
F80048052961850500E6868A /* StatusData+CoreDataClass.swift in Sources */,
F891E7CE29C35BF50022C449 /* ImageRowItem.swift in Sources */,
F86B7221296C49A300EE59EC /* EmptyButtonStyle.swift in Sources */,
F80048042961850500E6868A /* AttachmentData+CoreDataProperties.swift in Sources */,
F8B758DE2AB9DD85000C8068 /* ColumnData.swift in Sources */,
F88E4D4A297EA0490057491A /* RouterPath.swift in Sources */,
F88E4D48297E90CD0057491A /* TrendStatusesView.swift in Sources */,
F800480A2961EA1900E6868A /* AttachmentDataHandler.swift in Sources */,
F80048032961850500E6868A /* AttachmentData+CoreDataClass.swift in Sources */,
F891E7D029C368750022C449 /* ImageRowItemAsync.swift in Sources */,
F89D6C4A297196FF001DA3D4 /* ImageViewer.swift in Sources */,
F8A93D7E2965FD89001D8331 /* UserProfileView.swift in Sources */,
F88C246E295C37B80006098B /* MainView.swift in Sources */,
F8AFF7C429B25EF40087D083 /* ImagesGrid.swift in Sources */,
F88C2478295C37BB0006098B /* Vernissage.xcdatamodeld in Sources */,
F8DE749F2AE4F7B500ACD188 /* NotificationsService.swift in Sources */,
F8AFF7C129B259150087D083 /* HashtagsView.swift in Sources */,
F8DF38E429DD68820047F1AA /* ViewOffsetKey.swift in Sources */,
F89A46DE296EABA20062125F /* StatusPlaceholderView.swift in Sources */,
@ -1235,13 +1124,10 @@
F8B0885E29942E31002AB40A /* ThirdPartyView.swift in Sources */,
F8E6D03329CDD52500416CCA /* EditProfileView.swift in Sources */,
F858906B29E1CC7A00D4BDED /* UIApplication+Window.swift in Sources */,
F865B4CD2A024AD8008ACDFC /* StatusData+Faulty.swift in Sources */,
F876418D298AE5020057D362 /* PaginableStatusesView.swift in Sources */,
F85D49852964301800751DF7 /* StatusData+Attachments.swift in Sources */,
F8764187298ABB520057D362 /* ViewState.swift in Sources */,
F870EE5229F1645C00A2D43B /* MainNavigationOptions.swift in Sources */,
F88ABD9429687CA4004EF61E /* ComposeView.swift in Sources */,
F89CEB802984198600A1376F /* AttachmentData+HighestImage.swift in Sources */,
F86B7214296BFDCE00EE59EC /* UserProfileHeaderView.swift in Sources */,
F85D497D29640D5900751DF7 /* InteractionRow.swift in Sources */,
F86167C6297FE6CC004D1F67 /* AvatarShapesSectionView.swift in Sources */,
@ -1252,10 +1138,11 @@
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */,
F86A4307299AA5E900DF7645 /* ThanksView.swift in Sources */,
F8FB8ABA29EB2ED400342C04 /* NavigationMenuButtons.swift in Sources */,
F88BC51D29E0377B00CE6141 /* AccountData+AccountModel.swift in Sources */,
F8D8E0CF2ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */,
F89B5CC229D01BF700549F2F /* InstanceView.swift in Sources */,
F825F0CB29F7CFC4008BD204 /* FollowRequestsView.swift in Sources */,
F825F0C929F7A562008BD204 /* UserProfilePrivateAccountView.swift in Sources */,
F8D0E5242AE2A88A0061C561 /* HomeTimelineService.swift in Sources */,
F89F57B029D1C11200001EE3 /* RelationshipModel.swift in Sources */,
F88AB05829B36B8200345EDE /* AccountsPhotoView.swift in Sources */,
F85D4971296402DC00751DF7 /* AuthorizationService.swift in Sources */,
@ -1264,9 +1151,12 @@
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */,
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */,
F86B7216296BFFDA00EE59EC /* UserProfileStatusesView.swift in Sources */,
F8D8E0CB2ACC237000AA1374 /* ViewedStatus.swift in Sources */,
F897978F29684BCB00B22335 /* LoadingView.swift in Sources */,
F8E7ADFE2AD44CEB0038FFFD /* AccountRelationship.swift in Sources */,
F89992C9296D6DC7005994BF /* CommentBodyView.swift in Sources */,
F866F6A1296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift in Sources */,
F866F6A1296040A8002E8F88 /* ApplicationSettings.swift in Sources */,
F8E7AE022AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */,
F86A4303299A9AF500DF7645 /* TipsStore.swift in Sources */,
F8DF38E629DDB98A0047F1AA /* SocialsSectionView.swift in Sources */,
F88BC53B29E06A5100CE6141 /* ImageContextMenu.swift in Sources */,
@ -1276,6 +1166,7 @@
F89A46DC296EAACE0062125F /* SettingsView.swift in Sources */,
F866F6AE29606367002E8F88 /* ApplicationViewMode.swift in Sources */,
F8675DD02A1FA40500A89959 /* WaterfallGrid.swift in Sources */,
F886BBAC2AE7CF510083152B /* NotificationView.swift in Sources */,
F85D4DFE29B78C8400345267 /* HashtagModel.swift in Sources */,
F866F6AA29605AFA002E8F88 /* SceneDelegate.swift in Sources */,
);
@ -1296,20 +1187,6 @@
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
F835082629BEF9C400DE3247 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
F835082529BEF9C400DE3247 /* en */,
F835082729BEFA1E00DE3247 /* pl */,
F8DF38E729DDC3D20047F1AA /* eu */,
F8A270DA29F500860062D275 /* fr */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
F864F76E29BB91B600B13921 /* Debug */ = {
isa = XCBuildConfiguration;
@ -1321,22 +1198,25 @@
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 211;
CURRENT_PROJECT_VERSION = 305;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = VernissageWidget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 2.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1352,22 +1232,25 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 211;
CURRENT_PROJECT_VERSION = 305;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = VernissageWidget;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 2.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.widget;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1382,22 +1265,25 @@
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 211;
CURRENT_PROJECT_VERSION = 305;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageShare/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = VernissageShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 2.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1411,22 +1297,25 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = NO;
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 211;
CURRENT_PROJECT_VERSION = 305;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageShare/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = VernissageShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 2.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage.share;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1486,7 +1375,8 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@ -1543,7 +1433,8 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
@ -1557,7 +1448,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "Violet Blue Pride Pride-Camera Blue-Camera Violet-Camera Orange-Camera Orange Yellow-Camera Yellow Gradient-Camera Gradient";
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "Violet Blue Pride Pride-Camera Blue-Camera Violet-Camera Orange-Camera Orange Yellow-Camera Yellow Gradient-Camera Gradient Brown-Lens Pink-Lens Blue-Lens Orange-Lens";
ASSETCATALOG_COMPILER_APPICON_NAME = Default;
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = NO;
@ -1565,7 +1456,7 @@
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 211;
CURRENT_PROJECT_VERSION = 305;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@ -1579,18 +1470,18 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 2.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1601,14 +1492,14 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "Violet Blue Pride Pride-Camera Blue-Camera Violet-Camera Orange-Camera Orange Yellow-Camera Yellow Gradient-Camera Gradient";
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "Violet Blue Pride Pride-Camera Blue-Camera Violet-Camera Orange-Camera Orange Yellow-Camera Yellow Gradient-Camera Gradient Brown-Lens Pink-Lens Blue-Lens Orange-Lens";
ASSETCATALOG_COMPILER_APPICON_NAME = Default;
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = NO;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 211;
CURRENT_PROJECT_VERSION = 305;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@ -1622,17 +1513,17 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 2.0.5;
PRODUCT_BUNDLE_IDENTIFIER = dev.mczachurski.vernissage;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1689,14 +1580,6 @@
minimumVersion = 12.0.0;
};
};
F84625F929FE393B002D3AF4 /* XCRemoteSwiftPackageReference "QRCode" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/dmrschmidt/QRCode";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.0;
};
};
F88E4D4B297EA4290057491A /* XCRemoteSwiftPackageReference "EmojiText" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/divadretlaw/EmojiText";
@ -1739,11 +1622,6 @@
package = F8210DD32966BB7E001D9973 /* XCRemoteSwiftPackageReference "Nuke" */;
productName = NukeUI;
};
F84625FA29FE393B002D3AF4 /* QRCode */ = {
isa = XCSwiftPackageProductDependency;
package = F84625F929FE393B002D3AF4 /* XCRemoteSwiftPackageReference "QRCode" */;
productName = QRCode;
};
F864F77929BB94A800B13921 /* PixelfedKit */ = {
isa = XCSwiftPackageProductDependency;
productName = PixelfedKit;
@ -1800,33 +1678,6 @@
productName = Semaphore;
};
/* End XCSwiftPackageProductDependency section */
/* Begin XCVersionGroup section */
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
F8206A032A06547600E19412 /* Vernissage-014.xcdatamodel */,
F865B4D42A0252FB008ACDFC /* Vernissage-013.xcdatamodel */,
F8EF3C8B29FC3A5F00CBFF7C /* Vernissage-012.xcdatamodel */,
F871F21F29EF0FEC00A351EF /* Vernissage-011.xcdatamodel */,
F85B586C29ED169B00A16D12 /* Vernissage-010.xcdatamodel */,
F8FFBD4929E99BEE0047EE80 /* Vernissage-009.xcdatamodel */,
F8A4A88429E4099900267E36 /* Vernissage-008.xcdatamodel */,
F8911A1829DE9E5500770F44 /* Vernissage-007.xcdatamodel */,
F8EF371429C624DA00669F45 /* Vernissage-006.xcdatamodel */,
F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */,
F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */,
F8B05AC929B488C600857221 /* Vernissage-003.xcdatamodel */,
F89F0605299139F6003DC875 /* Vernissage-002.xcdatamodel */,
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */,
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
);
currentVersion = F8206A032A06547600E19412 /* Vernissage-014.xcdatamodel */;
path = Vernissage.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = F88C2460295C37B80006098B /* Project object */;
}

View File

@ -1,14 +1,5 @@
{
"pins" : [
{
"identity" : "activityindicatorview",
"kind" : "remoteSourceControl",
"location" : "https://github.com/exyte/ActivityIndicatorView.git",
"state" : {
"revision" : "9970fd0bb7a05dad0b6566ae1f56937716686b24",
"version" : "1.1.1"
}
},
{
"identity" : "brightfutures",
"kind" : "remoteSourceControl",
@ -23,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/omaralbeik/Drops",
"state" : {
"revision" : "f4eabe3e4e5da69e5205a69a5ddc0effd4a90519",
"version" : "1.6.1"
"revision" : "a183ee6f79f21c940092a19c2cba756555422371",
"version" : "1.7.0"
}
},
{
@ -86,8 +77,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/kean/Nuke",
"state" : {
"revision" : "3f666f120b63ea7de57d42e9a7c9b47f8e7a290b",
"version" : "12.1.6"
"revision" : "1694798e876113d44f6ec6ead965d7286695981d",
"version" : "12.2.0"
}
},
{
@ -99,15 +90,6 @@
"version" : "2.2.0"
}
},
{
"identity" : "qrcode",
"kind" : "remoteSourceControl",
"location" : "https://github.com/dmrschmidt/QRCode",
"state" : {
"revision" : "a23c2d2b77483c5ce20ffaf4e68fef2d1a0bbca9",
"version" : "1.1.0"
}
},
{
"identity" : "semaphore",
"kind" : "remoteSourceControl",

View File

@ -15,5 +15,5 @@ class AppDelegate: NSObject, UIApplicationDelegate {
let sceneConfig: UISceneConfiguration = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
sceneConfig.delegateClass = SceneDelegate.self
return sceneConfig
}
}
}

View File

@ -8,8 +8,8 @@ import Foundation
import SwiftUI
import WidgetsKit
@MainActor
extension View {
func withAppRouteur() -> some View {
self.navigationDestination(for: RouteurDestinations.self) { destination in
switch destination {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "Blue-Lens-Preview.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Blue-Lens-Preview@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Blue-Lens-Preview@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 KiB

View File

@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "BlueLens.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "Brown-Lens-Preview.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Brown-Lens-Preview@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Brown-Lens-Preview@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

View File

@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "BrownLens.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "Lens-Preview.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Lens-Preview@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Lens-Preview@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Some files were not shown because too many files have changed in this diff Show More