forked from zelo72/mastodon-ios
Merge branch 'feature/new-iPad' into release/1.2.0
This commit is contained in:
commit
0032365816
|
@ -17,6 +17,6 @@
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.2.0</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>79</string>
|
<string>83</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -17,6 +17,6 @@
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.2.0</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>79</string>
|
<string>83</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -17,6 +17,6 @@
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.2.0</string>
|
<string>1.2.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>79</string>
|
<string>83</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
"16wxgf" = "Post on Mastodon";
|
"16wxgf" = "النَشر على ماستودون";
|
||||||
|
|
||||||
"751xkl" = "محتوى نصي";
|
"751xkl" = "محتوى نصي";
|
||||||
|
|
||||||
"CsR7G2" = "انشر على ماستدون";
|
"CsR7G2" = "انشر على ماستدون";
|
||||||
|
|
||||||
"HZSGTr" = "What content to post?";
|
"HZSGTr" = "ما المُحتوى المُراد نشره؟";
|
||||||
|
|
||||||
"HdGikU" = "Posting failed";
|
"HdGikU" = "فَشَلَ النشر";
|
||||||
|
|
||||||
"KDNTJ4" = "سبب الإخفاق";
|
"KDNTJ4" = "سبب الإخفاق";
|
||||||
|
|
||||||
"RHxKOw" = "Send Post with text content";
|
"RHxKOw" = "إرسال مَنشور يَحوي نص";
|
||||||
|
|
||||||
"RxSqsb" = "Post";
|
"RxSqsb" = "مَنشور";
|
||||||
|
|
||||||
"WCIR3D" = "Post ${content} on Mastodon";
|
"WCIR3D" = "نَشر ${content} على ماستودون";
|
||||||
|
|
||||||
"ZKJSNu" = "Post";
|
"ZKJSNu" = "مَنشور";
|
||||||
|
|
||||||
"ZS1XaK" = "${content}";
|
"ZS1XaK" = "${content}";
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@
|
||||||
|
|
||||||
"Zo4jgJ" = "مدى ظهور المنشور";
|
"Zo4jgJ" = "مدى ظهور المنشور";
|
||||||
|
|
||||||
"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’.";
|
"apSxMG-dYQ5NN" = "هُناك عدد ${count} خِيار مُطابق لِـ\"عام\".";
|
||||||
|
|
||||||
"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’.";
|
"apSxMG-ehFLjY" = "هُناك عدد ${count} خِيار مُطابق لِـ\"المُتابِعُون فقط\".";
|
||||||
|
|
||||||
"ayoYEb-dYQ5NN" = "${content}, Public";
|
"ayoYEb-dYQ5NN" = "${content}، عام";
|
||||||
|
|
||||||
"ayoYEb-ehFLjY" = "${content}, Followers Only";
|
"ayoYEb-ehFLjY" = "${content}، المُتابِعُون فقط";
|
||||||
|
|
||||||
"dUyuGg" = "النشر على ماستدون";
|
"dUyuGg" = "النشر على ماستدون";
|
||||||
|
|
||||||
|
@ -38,13 +38,13 @@
|
||||||
|
|
||||||
"ehFLjY" = "لمتابعيك فقط";
|
"ehFLjY" = "لمتابعيك فقط";
|
||||||
|
|
||||||
"gfePDu" = "Posting failed. ${failureReason}";
|
"gfePDu" = "فَشَلَ النشر، ${failureReason}";
|
||||||
|
|
||||||
"k7dbKQ" = "Post was sent successfully.";
|
"k7dbKQ" = "تمَّ إرسال المنشور بِنجاح.";
|
||||||
|
|
||||||
"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?";
|
"oGiqmY-dYQ5NN" = "للتأكيد، هل تَريد \"عام\"؟";
|
||||||
|
|
||||||
"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?";
|
"oGiqmY-ehFLjY" = "للتأكيد، هل تُريد \"للمُتابِعين فقط\"؟";
|
||||||
|
|
||||||
"rM6dvp" = "عنوان URL";
|
"rM6dvp" = "عنوان URL";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
"16wxgf" = "Di Mastodon de biweşîne";
|
||||||
|
|
||||||
|
"751xkl" = "Naveroka nivîsê";
|
||||||
|
|
||||||
|
"CsR7G2" = "Di Mastodon de biweşîne";
|
||||||
|
|
||||||
|
"HZSGTr" = "Kîjan naverok bila bê şandin?";
|
||||||
|
|
||||||
|
"HdGikU" = "Şandin têkçû";
|
||||||
|
|
||||||
|
"KDNTJ4" = "Sedema têkçûnê";
|
||||||
|
|
||||||
|
"RHxKOw" = "Bi naveroka nivîsî şandiyan bişîne";
|
||||||
|
|
||||||
|
"RxSqsb" = "Şandî";
|
||||||
|
|
||||||
|
"WCIR3D" = "${content} biweşîne di Mastodon de";
|
||||||
|
|
||||||
|
"ZKJSNu" = "Şandî";
|
||||||
|
|
||||||
|
"ZS1XaK" = "${content}";
|
||||||
|
|
||||||
|
"ZbSjzC" = "Xuyanî";
|
||||||
|
|
||||||
|
"Zo4jgJ" = "Xuyaniya şandiyê";
|
||||||
|
|
||||||
|
"apSxMG-dYQ5NN" = "Vebijarkên ${count} hene ku li gorî 'Giştî' ne.";
|
||||||
|
|
||||||
|
"apSxMG-ehFLjY" = "Vebijarkên ${count} hene ku li gorî 'Tenê Şopandin' hene.";
|
||||||
|
|
||||||
|
"ayoYEb-dYQ5NN" = "${content}, Giştî";
|
||||||
|
|
||||||
|
"ayoYEb-ehFLjY" = "${content}, Tenê şopînêr";
|
||||||
|
|
||||||
|
"dUyuGg" = "Li ser Mastodon bişînin";
|
||||||
|
|
||||||
|
"dYQ5NN" = "Gelemperî";
|
||||||
|
|
||||||
|
"ehFLjY" = "Tenê şopîneran";
|
||||||
|
|
||||||
|
"gfePDu" = "Weşandin bi ser neket. ${failureReason}";
|
||||||
|
|
||||||
|
"k7dbKQ" = "Şandî bi serkeftî hate şandin.";
|
||||||
|
|
||||||
|
"oGiqmY-dYQ5NN" = "Tenê ji bo pejirandinê, we 'Giştî' dixwest?";
|
||||||
|
|
||||||
|
"oGiqmY-ehFLjY" = "Tenê ji bo piştrastkirinê, we 'Tenê Şopdarên' dixwest?";
|
||||||
|
|
||||||
|
"rM6dvp" = "Girêdan";
|
||||||
|
|
||||||
|
"ryJLwG" = "Bi serkeftî hat şandin. ";
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?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>There are ${count} options matching ‘${content}’. - 2</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_option@ heye ku bi ‘${content}’ re têkildar e.</string>
|
||||||
|
<key>count_option</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>%ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 vebijêrk</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld vebijêrk</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>There are ${count} options matching ‘${visibility}’.</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_option@ heye ku bi ‘${visibility}’ re têkildar e.</string>
|
||||||
|
<key>count_option</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>%ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 vebijêrk</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld vebijêrk</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -5,7 +5,7 @@
|
||||||
<key>There are ${count} options matching ‘${content}’. - 2</key>
|
<key>There are ${count} options matching ‘${content}’. - 2</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>There are %#@count_option@ matching ‘${content}’.</string>
|
<string>Er zijn %#@count_option@ die overeenkomen met ‘${content}’.</string>
|
||||||
<key>count_option</key>
|
<key>count_option</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>%ld</string>
|
<string>%ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>1 option</string>
|
<string>1 optie</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld options</string>
|
<string>%ld options</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<key>There are ${count} options matching ‘${visibility}’.</key>
|
<key>There are ${count} options matching ‘${visibility}’.</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>There are %#@count_option@ matching ‘${visibility}’.</string>
|
<string>Er zijn %#@count_option@ die overeenkomen met ‘${visibility}’.</string>
|
||||||
<key>count_option</key>
|
<key>count_option</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>%ld</string>
|
<string>%ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>1 option</string>
|
<string>1 optie</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld options</string>
|
<string>%ld options</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -51,6 +51,7 @@ private func map(language: String) -> String? {
|
||||||
case "fr_FR": return "fr" // French
|
case "fr_FR": return "fr" // French
|
||||||
case "de_DE": return "de" // German
|
case "de_DE": return "de" // German
|
||||||
case "ja_JP": return "ja" // Japanese
|
case "ja_JP": return "ja" // Japanese
|
||||||
|
case "kmr_TR": return "ku-TR" // Kurmanji (Kurdish)
|
||||||
case "ru_RU": return "ru" // Russian
|
case "ru_RU": return "ru" // Russian
|
||||||
case "gd_GB": return "gd-GB" // Scottish Gaelic
|
case "gd_GB": return "gd-GB" // Scottish Gaelic
|
||||||
case "es_ES": return "es" // Spanish
|
case "es_ES": return "es" // Spanish
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"edit_profile_failure": {
|
"edit_profile_failure": {
|
||||||
"title": "Edit Profile Error",
|
"title": "خطأ في تَحرير الملف الشخصي",
|
||||||
"message": "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى."
|
"message": "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى."
|
||||||
},
|
},
|
||||||
"sign_out": {
|
"sign_out": {
|
||||||
|
@ -67,6 +67,7 @@
|
||||||
"done": "تمّ",
|
"done": "تمّ",
|
||||||
"confirm": "تأكيد",
|
"confirm": "تأكيد",
|
||||||
"continue": "واصل",
|
"continue": "واصل",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "إلغاء",
|
"cancel": "إلغاء",
|
||||||
"discard": "تجاهل",
|
"discard": "تجاهل",
|
||||||
"try_again": "المُحاولة مرة أُخرى",
|
"try_again": "المُحاولة مرة أُخرى",
|
||||||
|
@ -194,12 +195,12 @@
|
||||||
"slogan": "Social networking\nback in your hands."
|
"slogan": "Social networking\nback in your hands."
|
||||||
},
|
},
|
||||||
"server_picker": {
|
"server_picker": {
|
||||||
"title": "Pick a server,\nany server.",
|
"title": "اِختر خادِم،\nأي خادِم.",
|
||||||
"button": {
|
"button": {
|
||||||
"category": {
|
"category": {
|
||||||
"all": "الكل",
|
"all": "الكل",
|
||||||
"all_accessiblity_description": "الفئة: الكل",
|
"all_accessiblity_description": "الفئة: الكل",
|
||||||
"academia": "academia",
|
"academia": "أكاديمي",
|
||||||
"activism": "للنشطاء",
|
"activism": "للنشطاء",
|
||||||
"food": "الطعام",
|
"food": "الطعام",
|
||||||
"furry": "فروي",
|
"furry": "فروي",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "بحث",
|
"title": "بحث",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<key>a11y.plural.count.input_limit_exceeds</key>
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>El límit d’entrada supera a %#@character_count@</string>
|
<string>El límit de la entrada supera a %#@character_count@</string>
|
||||||
<key>character_count</key>
|
<key>character_count</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<key>a11y.plural.count.input_limit_remains</key>
|
<key>a11y.plural.count.input_limit_remains</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>El límit d’entrada continua sent %#@character_count@</string>
|
<string>El límit de la entrada continua sent %#@character_count@</string>
|
||||||
<key>character_count</key>
|
<key>character_count</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>1 impuls</string>
|
<string>1 impuls</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld impuls</string>
|
<string>%ld impulsos</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>plural.count.vote</key>
|
<key>plural.count.vote</key>
|
||||||
|
@ -301,9 +301,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1a</string>
|
<string>fa 1 any</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldy anys</string>
|
<string>fa %ld anys</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.month.ago.abbr</key>
|
<key>date.month.ago.abbr</key>
|
||||||
|
@ -317,9 +317,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1M</string>
|
<string>fa 1 mes</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldM mesos</string>
|
<string>fa %ld mesos</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.day.ago.abbr</key>
|
<key>date.day.ago.abbr</key>
|
||||||
|
@ -333,9 +333,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1d</string>
|
<string>fa 1 día</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldd dies</string>
|
<string>fa %ld dies</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.hour.ago.abbr</key>
|
<key>date.hour.ago.abbr</key>
|
||||||
|
@ -351,7 +351,7 @@
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1h</string>
|
<string>fa 1h</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldh hores</string>
|
<string>fa %ld hores</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.minute.ago.abbr</key>
|
<key>date.minute.ago.abbr</key>
|
||||||
|
@ -365,9 +365,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1m</string>
|
<string>fa 1 minut</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldm minuts</string>
|
<string>fa %ld minuts</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.second.ago.abbr</key>
|
<key>date.second.ago.abbr</key>
|
||||||
|
@ -381,9 +381,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1s</string>
|
<string>fa 1 segon</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %lds seg</string>
|
<string>fa %ld segons</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Fet",
|
"done": "Fet",
|
||||||
"confirm": "Confirma",
|
"confirm": "Confirma",
|
||||||
"continue": "Continua",
|
"continue": "Continua",
|
||||||
|
"compose": "Composa",
|
||||||
"cancel": "Cancel·la",
|
"cancel": "Cancel·la",
|
||||||
"discard": "Descarta",
|
"discard": "Descarta",
|
||||||
"try_again": "Torna a provar",
|
"try_again": "Torna a provar",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Els seguidors d'altres servidors no son mostrats."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Els seguits d'altres servidors no son mostrats."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Cerca",
|
"title": "Cerca",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Fertig",
|
"done": "Fertig",
|
||||||
"confirm": "Bestätigen",
|
"confirm": "Bestätigen",
|
||||||
"continue": "Fortfahren",
|
"continue": "Fortfahren",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"discard": "Verwerfen",
|
"discard": "Verwerfen",
|
||||||
"try_again": "Nochmals versuchen",
|
"try_again": "Nochmals versuchen",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Suche",
|
"title": "Suche",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
@ -536,13 +543,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"account_list": {
|
"account_list": {
|
||||||
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
|
"tab_bar_hint": "Aktuell ausgewähltes Profil: %s. Doppeltippen dann gedrückt halten, um den Kontoschalter anzuzeigen",
|
||||||
"dismiss_account_switcher": "Dismiss Account Switcher",
|
"dismiss_account_switcher": "Dismiss Account Switcher",
|
||||||
"add_account": "Konto hinzufügen"
|
"add_account": "Konto hinzufügen"
|
||||||
},
|
},
|
||||||
"wizard": {
|
"wizard": {
|
||||||
"new_in_mastodon": "Neu in Mastodon",
|
"new_in_mastodon": "Neu in Mastodon",
|
||||||
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
|
"multiple_account_switch_intro_description": "Wechsel zwischen mehreren Konten durch drücken der Profil-Schaltfläche.",
|
||||||
"accessibility_hint": "Doppeltippen, um diesen Assistenten zu schließen"
|
"accessibility_hint": "Doppeltippen, um diesen Assistenten zu schließen"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Listo",
|
"done": "Listo",
|
||||||
"confirm": "Confirmar",
|
"confirm": "Confirmar",
|
||||||
"continue": "Continuar",
|
"continue": "Continuar",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"discard": "Descartar",
|
"discard": "Descartar",
|
||||||
"try_again": "Intentá de nuevo",
|
"try_again": "Intentá de nuevo",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Buscar",
|
"title": "Buscar",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Hecho",
|
"done": "Hecho",
|
||||||
"confirm": "Confirmar",
|
"confirm": "Confirmar",
|
||||||
"continue": "Continuar",
|
"continue": "Continuar",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"discard": "Descartar",
|
"discard": "Descartar",
|
||||||
"try_again": "Inténtalo de nuevo",
|
"try_again": "Inténtalo de nuevo",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Buscar",
|
"title": "Buscar",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Terminé",
|
"done": "Terminé",
|
||||||
"confirm": "Confirmer",
|
"confirm": "Confirmer",
|
||||||
"continue": "Continuer",
|
"continue": "Continuer",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Annuler",
|
"cancel": "Annuler",
|
||||||
"discard": "Abandonner",
|
"discard": "Abandonner",
|
||||||
"try_again": "Réessayer",
|
"try_again": "Réessayer",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Rechercher",
|
"title": "Rechercher",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>1 unread notification</string>
|
<string>%ld bhrath nach deach a leughadh</string>
|
||||||
<key>two</key>
|
<key>two</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld bhrath nach deach a leughadh</string>
|
||||||
<key>few</key>
|
<key>few</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld brathan nach deach a leughadh</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld brath nach deach a leughadh</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>a11y.plural.count.input_limit_exceeds</key>
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Deiseil",
|
"done": "Deiseil",
|
||||||
"confirm": "Dearbh",
|
"confirm": "Dearbh",
|
||||||
"continue": "Lean air adhart",
|
"continue": "Lean air adhart",
|
||||||
|
"compose": "Sgrìobh",
|
||||||
"cancel": "Sguir dheth",
|
"cancel": "Sguir dheth",
|
||||||
"discard": "Tilg air falbh",
|
"discard": "Tilg air falbh",
|
||||||
"try_again": "Feuch ris a-rithist",
|
"try_again": "Feuch ris a-rithist",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Cha dèid luchd-leantainn o fhrithealaichean eile a shealltainn."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Cha dèid cò air a leanas tu air frithealaichean eile a shealltainn."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Lorg",
|
"title": "Lorg",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
@ -536,14 +543,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"account_list": {
|
"account_list": {
|
||||||
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
|
"tab_bar_hint": "A’ phròifil air a taghadh: %s. Thoir gnogag dhùbailte is cùm sìos a ghearradh leum gu cunntas eile",
|
||||||
"dismiss_account_switcher": "Dismiss Account Switcher",
|
"dismiss_account_switcher": "Leig seachad taghadh a’ chunntais",
|
||||||
"add_account": "Add Account"
|
"add_account": "Cuir cunntas ris"
|
||||||
},
|
},
|
||||||
"wizard": {
|
"wizard": {
|
||||||
"new_in_mastodon": "New in Mastodon",
|
"new_in_mastodon": "Na tha ùr ann am Mastodon",
|
||||||
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
|
"multiple_account_switch_intro_description": "Geàrr leum eadar iomadh cunntas le cumail sìos putan na pròifil.",
|
||||||
"accessibility_hint": "Double tap to dismiss this wizard"
|
"accessibility_hint": "Thoir gnogag dhùbailte a’ leigeil seachad an draoidh seo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Selesai",
|
"done": "Selesai",
|
||||||
"confirm": "Konfirmasi",
|
"confirm": "Konfirmasi",
|
||||||
"continue": "Lanjut",
|
"continue": "Lanjut",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Batal",
|
"cancel": "Batal",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Coba Lagi",
|
"try_again": "Coba Lagi",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Cari",
|
"title": "Cari",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld 件の未読通知</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>a11y.plural.count.input_limit_exceeds</key>
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld characters</string>
|
<string>%ld 文字</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>a11y.plural.count.input_limit_remains</key>
|
<key>a11y.plural.count.input_limit_remains</key>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld characters</string>
|
<string>%ld 文字</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>plural.count.metric_formatted.post</key>
|
<key>plural.count.metric_formatted.post</key>
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld votes</string>
|
<string>%ld票</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>plural.count.voter</key>
|
<key>plural.count.voter</key>
|
||||||
|
@ -195,7 +195,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld months left</string>
|
<string>%ldか月前</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.day.left</key>
|
<key>date.day.left</key>
|
||||||
|
@ -279,7 +279,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ldM ago</string>
|
<string>%ld分前</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.day.ago.abbr</key>
|
<key>date.day.ago.abbr</key>
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "完了",
|
"done": "完了",
|
||||||
"confirm": "確認",
|
"confirm": "確認",
|
||||||
"continue": "続ける",
|
"continue": "続ける",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "キャンセル",
|
"cancel": "キャンセル",
|
||||||
"discard": "破棄",
|
"discard": "破棄",
|
||||||
"try_again": "再実行",
|
"try_again": "再実行",
|
||||||
|
@ -191,7 +192,7 @@
|
||||||
},
|
},
|
||||||
"scene": {
|
"scene": {
|
||||||
"welcome": {
|
"welcome": {
|
||||||
"slogan": "Social networking\nback in your hands."
|
"slogan": "ソーシャルネットワーキングを、あなたの手の中に."
|
||||||
},
|
},
|
||||||
"server_picker": {
|
"server_picker": {
|
||||||
"title": "サーバーを選択",
|
"title": "サーバーを選択",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "検索",
|
"title": "検索",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
@ -538,11 +545,11 @@
|
||||||
"account_list": {
|
"account_list": {
|
||||||
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
|
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
|
||||||
"dismiss_account_switcher": "Dismiss Account Switcher",
|
"dismiss_account_switcher": "Dismiss Account Switcher",
|
||||||
"add_account": "Add Account"
|
"add_account": "アカウントを追加"
|
||||||
},
|
},
|
||||||
"wizard": {
|
"wizard": {
|
||||||
"new_in_mastodon": "New in Mastodon",
|
"new_in_mastodon": "Mastodon の新機能",
|
||||||
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
|
"multiple_account_switch_intro_description": "プロフィールボタンを押して複数のアカウントを切り替えます。",
|
||||||
"accessibility_hint": "Double tap to dismiss this wizard"
|
"accessibility_hint": "Double tap to dismiss this wizard"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,390 @@
|
||||||
|
<?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>a11y.plural.count.unread.notification</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@notification_count_unread_notification@</string>
|
||||||
|
<key>notification_count_unread_notification</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 agahdariya nexwendî</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld agahdariyên nexwendî</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>Sînorê têketinê derbas kir %#@character_count@</string>
|
||||||
|
<key>character_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 tîp</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld tîp</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>a11y.plural.count.input_limit_remains</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>Sînorê têketinê %#@character_count@ maye</string>
|
||||||
|
<key>character_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 tîp</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld tîp</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.metric_formatted.post</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%@ %#@post_count@</string>
|
||||||
|
<key>post_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>şandî</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>şandî</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.post</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@post_count@</string>
|
||||||
|
<key>post_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 şandî</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld şandî</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.favorite</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@favorite_count@</string>
|
||||||
|
<key>favorite_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 hezkirin</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld hezkirin</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.reblog</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@reblog_count@</string>
|
||||||
|
<key>reblog_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 ji nû ve nivîsandin</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld ji nû ve nivîsandin</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.vote</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@vote_count@</string>
|
||||||
|
<key>vote_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 deng</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld deng</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.voter</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@voter_count@</string>
|
||||||
|
<key>voter_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 hilbijêr</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld hilbijêr</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.people_talking</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_people_talking@</string>
|
||||||
|
<key>count_people_talking</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 mirov diaxive</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld mirov diaxive</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.following</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_following@</string>
|
||||||
|
<key>count_following</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 dişopîne</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld dişopîne</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.follower</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_follower@</string>
|
||||||
|
<key>count_follower</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 şopîner</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld şopîner</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.year.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_year_left@</string>
|
||||||
|
<key>count_year_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 sal berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld sal berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.month.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_month_left@</string>
|
||||||
|
<key>count_month_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 meh berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld meh berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.day.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_day_left@</string>
|
||||||
|
<key>count_day_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 roj berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld roj berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.hour.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_hour_left@</string>
|
||||||
|
<key>count_hour_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 demjimêr berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld demjimêr berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.minute.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_minute_left@</string>
|
||||||
|
<key>count_minute_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 xulek berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld xulek berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.second.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_second_left@</string>
|
||||||
|
<key>count_second_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 çirke berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld çirke berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.year.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_year_ago_abbr@</string>
|
||||||
|
<key>count_year_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 sal berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld sal berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.month.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_month_ago_abbr@</string>
|
||||||
|
<key>count_month_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 xulek berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld xulek berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.day.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_day_ago_abbr@</string>
|
||||||
|
<key>count_day_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 roj berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld roj berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.hour.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_hour_ago_abbr@</string>
|
||||||
|
<key>count_hour_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 demjimêr berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld demjimêr berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.minute.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_minute_ago_abbr@</string>
|
||||||
|
<key>count_minute_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 xulek berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld xulek berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.second.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_second_ago_abbr@</string>
|
||||||
|
<key>count_second_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 çirke berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld çirke berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,556 @@
|
||||||
|
{
|
||||||
|
"common": {
|
||||||
|
"alerts": {
|
||||||
|
"common": {
|
||||||
|
"please_try_again": "Ji kerema xwe dîsa biceribîne.",
|
||||||
|
"please_try_again_later": "Ji kerema xwe paşê dîsa biceribîne."
|
||||||
|
},
|
||||||
|
"sign_up_failure": {
|
||||||
|
"title": "Tomarkirin têkçû"
|
||||||
|
},
|
||||||
|
"server_error": {
|
||||||
|
"title": "Çewtiya rajekar"
|
||||||
|
},
|
||||||
|
"vote_failure": {
|
||||||
|
"title": "Dengdayîn têkçû",
|
||||||
|
"poll_ended": "Rapirsîya qediya"
|
||||||
|
},
|
||||||
|
"discard_post_content": {
|
||||||
|
"title": "Reşnivîs jêbibe",
|
||||||
|
"message": "Piştrast bikin ku naveroka posteyê ya hatîye nivîsandin jê bibin."
|
||||||
|
},
|
||||||
|
"publish_post_failure": {
|
||||||
|
"title": "Weşandin têkçû",
|
||||||
|
"message": "Weşandina şandiyê têkçû.\nJkx girêdana înternetê xwe kontrol bike.",
|
||||||
|
"attachments_message": {
|
||||||
|
"video_attach_with_photo": "Nikare vîdyoyekê tevlî şandiyê ku berê wêne tê de heye bike.",
|
||||||
|
"more_than_one_video": "Nikare ji bêtirî yek vîdyoyekê tevlî şandiyê bike."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"edit_profile_failure": {
|
||||||
|
"title": "Çewtiya profîlê biguherîne",
|
||||||
|
"message": "Nikare profîlê serrast bike. Jkx dîsa biceribîne."
|
||||||
|
},
|
||||||
|
"sign_out": {
|
||||||
|
"title": "Derkeve",
|
||||||
|
"message": "Ma tu dixwazî ku derkevî?",
|
||||||
|
"confirm": "Derkeve"
|
||||||
|
},
|
||||||
|
"block_domain": {
|
||||||
|
"title": "Tu ji xwe bawerî, bi rastî tu dixwazî hemû %s asteng bikî? Di gelek rewşan de asteng kirin an jî bêdeng kirin têrê dike û tê tercîh kirin. Tu nikarî naveroka vê navperê di demnameyê an jî agahdariyên xwe de bibînî. Şopînerên te yê di vê navperê were jêbirin.",
|
||||||
|
"block_entire_domain": "Navperê asteng bike"
|
||||||
|
},
|
||||||
|
"save_photo_failure": {
|
||||||
|
"title": "Tomarkirina wêneyê têkçû",
|
||||||
|
"message": "Ji kerema xwe destûra gihîştina pirtûkxaneya wêneyê çalak bikin da ku wêneyê hilînin."
|
||||||
|
},
|
||||||
|
"delete_post": {
|
||||||
|
"title": "Ma tu dixwazî vê şandiyê jê bibî?",
|
||||||
|
"delete": "Jê bibe"
|
||||||
|
},
|
||||||
|
"clean_cache": {
|
||||||
|
"title": "Pêşbîrê paqij bike",
|
||||||
|
"message": "Pêşbîra %s biserketî hate paqijkirin."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"controls": {
|
||||||
|
"actions": {
|
||||||
|
"back": "Vegere",
|
||||||
|
"next": "Pêş",
|
||||||
|
"previous": "Paş",
|
||||||
|
"open": "Veke",
|
||||||
|
"add": "Tevlî bike",
|
||||||
|
"remove": "Rake",
|
||||||
|
"edit": "Serrast bike",
|
||||||
|
"save": "Tomar bike",
|
||||||
|
"ok": "BAŞ E",
|
||||||
|
"done": "Qediya",
|
||||||
|
"confirm": "Bipejirîne",
|
||||||
|
"continue": "Bidomîne",
|
||||||
|
"compose": "Binivîsîne",
|
||||||
|
"cancel": "Dev jê berde",
|
||||||
|
"discard": "Biavêje",
|
||||||
|
"try_again": "Dîsa biceribîne",
|
||||||
|
"take_photo": "Wêne bikişîne",
|
||||||
|
"save_photo": "Wêneyê hilîne",
|
||||||
|
"copy_photo": "Wêne kopî bikin",
|
||||||
|
"sign_in": "Têkeve",
|
||||||
|
"sign_up": "Tomar bibe",
|
||||||
|
"see_more": "Bêtir bibîne",
|
||||||
|
"preview": "Pêşdîtin",
|
||||||
|
"share": "Parve bike",
|
||||||
|
"share_user": "%s parve bike",
|
||||||
|
"share_post": "Şandiyê parve bike",
|
||||||
|
"open_in_safari": "Di Safariyê de veke",
|
||||||
|
"find_people": "Kesên ku bişopînin bibînin",
|
||||||
|
"manually_search": "Ji devlê i destan lêgerînê bike",
|
||||||
|
"skip": "Derbas bike",
|
||||||
|
"reply": "Bersivê bide",
|
||||||
|
"report_user": "%s ragihîne",
|
||||||
|
"block_domain": "%s asteng bike",
|
||||||
|
"unblock_domain": "%s asteng neke",
|
||||||
|
"settings": "Sazkarî",
|
||||||
|
"delete": "Jê bibe"
|
||||||
|
},
|
||||||
|
"tabs": {
|
||||||
|
"home": "Serrûpel",
|
||||||
|
"search": "Bigere",
|
||||||
|
"notification": "Agahdarî",
|
||||||
|
"profile": "Profîl"
|
||||||
|
},
|
||||||
|
"keyboard": {
|
||||||
|
"common": {
|
||||||
|
"switch_to_tab": "Biguherîne bo %s",
|
||||||
|
"compose_new_post": "Şandiyeke nû binivsîne",
|
||||||
|
"show_favorites": "Bijarteyan nîşan bide",
|
||||||
|
"open_settings": "Sazkariyan Veke"
|
||||||
|
},
|
||||||
|
"timeline": {
|
||||||
|
"previous_status": "Şandeya paş",
|
||||||
|
"next_status": "Şandiya pêş",
|
||||||
|
"open_status": "Şandiyê veke",
|
||||||
|
"open_author_profile": "Profîla nivîskaran veke",
|
||||||
|
"open_reblogger_profile": "Profîla nivîskaran veke",
|
||||||
|
"reply_status": "Bersivê bide şandiyê",
|
||||||
|
"toggle_reblog": "Ji vû nivîsandin di şandiyê de biguherîne",
|
||||||
|
"toggle_favorite": "Di postê da Bijartin veke/bigire",
|
||||||
|
"toggle_content_warning": "Hişyariya naverokê veke/bigire",
|
||||||
|
"preview_image": "Wêneya pêşdîtinê"
|
||||||
|
},
|
||||||
|
"segmented_control": {
|
||||||
|
"previous_section": "Beşa berê",
|
||||||
|
"next_section": "Beşa paşê"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"user_reblogged": "%s ji nû ve hat blogkirin",
|
||||||
|
"user_replied_to": "Bersiv da %s",
|
||||||
|
"show_post": "Şandiyê nîşan bide",
|
||||||
|
"show_user_profile": "Profîla bikarhêner nîşan bide",
|
||||||
|
"content_warning": "Hişyariya naverokê",
|
||||||
|
"media_content_warning": "Ji bo aşkerakirinê derekî bitikîne",
|
||||||
|
"poll": {
|
||||||
|
"vote": "Deng",
|
||||||
|
"closed": "Girtî"
|
||||||
|
},
|
||||||
|
"actions": {
|
||||||
|
"reply": "Bersivê bide",
|
||||||
|
"reblog": "Ji nû ve blog",
|
||||||
|
"unreblog": "Ji nû ve blogkirin betal bikin",
|
||||||
|
"favorite": "Bijartî",
|
||||||
|
"unfavorite": "Nebijare",
|
||||||
|
"menu": "Menû"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"url": "URL",
|
||||||
|
"mention": "Behs",
|
||||||
|
"link": "Girêdan",
|
||||||
|
"hashtag": "Etîket",
|
||||||
|
"email": "E-name",
|
||||||
|
"emoji": "E-name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"friendship": {
|
||||||
|
"follow": "Bişopîne",
|
||||||
|
"following": "Dişopîne",
|
||||||
|
"request": "Daxwazên şopandinê",
|
||||||
|
"pending": "Tê nirxandin",
|
||||||
|
"block": "Asteng bike",
|
||||||
|
"block_user": "%s asteng bike",
|
||||||
|
"block_domain": "%s asteng bike",
|
||||||
|
"unblock": "Astengiyê rake",
|
||||||
|
"unblock_user": "%s asteng neke",
|
||||||
|
"blocked": "Astengkirî",
|
||||||
|
"mute": "Bêdeng bike",
|
||||||
|
"mute_user": "%s bêdeng bike",
|
||||||
|
"unmute": "Bêdeng neke",
|
||||||
|
"unmute_user": "%s bêdeng neke",
|
||||||
|
"muted": "Bêdengkirî",
|
||||||
|
"edit_info": "Zanyariyan serrast bike"
|
||||||
|
},
|
||||||
|
"timeline": {
|
||||||
|
"filtered": "Parzûnkirî",
|
||||||
|
"timestamp": {
|
||||||
|
"now": "Niha"
|
||||||
|
},
|
||||||
|
"loader": {
|
||||||
|
"load_missing_posts": "Barkirina posteyên kêm",
|
||||||
|
"loading_missing_posts": "Barkirina posteyên kêm...",
|
||||||
|
"show_more_replies": "Bêtir bersivan nîşan bide"
|
||||||
|
},
|
||||||
|
"header": {
|
||||||
|
"no_status_found": "Şandî nehate dîtin",
|
||||||
|
"blocking_warning": "Tu nikarî profîla vî bikarhênerî bibînî\nHeta ku tu wan asteng bikî.\nProfîla te ji wan ra wiha xuya dike.",
|
||||||
|
"user_blocking_warning": "Tu nikarî profîla %s bibînî\nHeta ku tu wan asteng bikî.\nProfîla te ji wan ra wiha xuya dike.",
|
||||||
|
"blocked_warning": "Tu nikarî profîla vî bikarhênerî bibînî\nheta ku astengîya te rakin.",
|
||||||
|
"user_blocked_warning": "Tu nikarî profîla %s bibînî\nHeta ku astengîya te rakin.",
|
||||||
|
"suspended_warning": "Ev bikarhêner hat sekinandin.",
|
||||||
|
"user_suspended_warning": "Hesaba %s hat sekinandin."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scene": {
|
||||||
|
"welcome": {
|
||||||
|
"slogan": "Torên civakî\ndi destên te de."
|
||||||
|
},
|
||||||
|
"server_picker": {
|
||||||
|
"title": "Rajekarekê hilbijêre,\nHer kîjan rajekar be.",
|
||||||
|
"button": {
|
||||||
|
"category": {
|
||||||
|
"all": "Hemû",
|
||||||
|
"all_accessiblity_description": "Beş: Hemû",
|
||||||
|
"academia": "akademî",
|
||||||
|
"activism": "çalakî",
|
||||||
|
"food": "xwarin",
|
||||||
|
"furry": "furry",
|
||||||
|
"games": "lîsk",
|
||||||
|
"general": "giştî",
|
||||||
|
"journalism": "rojnamevanî",
|
||||||
|
"lgbt": "lgbt",
|
||||||
|
"regional": "herêmî",
|
||||||
|
"art": "huner",
|
||||||
|
"music": "muzîk",
|
||||||
|
"tech": "teknolojî"
|
||||||
|
},
|
||||||
|
"see_less": "Kêmtir bibîne",
|
||||||
|
"see_more": "Bêtir bibîne"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"language": "ZIMAN",
|
||||||
|
"users": "BIKARHÊNER",
|
||||||
|
"category": "KATEGORÎ"
|
||||||
|
},
|
||||||
|
"input": {
|
||||||
|
"placeholder": "Serverek bibînin an jî beşdarî ya xwe bibin..."
|
||||||
|
},
|
||||||
|
"empty_state": {
|
||||||
|
"finding_servers": "Dîtina serverên berdest...",
|
||||||
|
"bad_network": "Di dema barkirina daneyan da tiştek xelet derket. Girêdana xwe ya înternetê kontrol bike.",
|
||||||
|
"no_results": "Encam nade"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"register": {
|
||||||
|
"title": "Ji me re hinekî qala xwe bike.",
|
||||||
|
"input": {
|
||||||
|
"avatar": {
|
||||||
|
"delete": "Jê bibe"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"placeholder": "navê bikarhêner",
|
||||||
|
"duplicate_prompt": "Navê vê bikarhêner tê girtin."
|
||||||
|
},
|
||||||
|
"display_name": {
|
||||||
|
"placeholder": "navê nîşanê"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"placeholder": "e-name"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"placeholder": "şîfre",
|
||||||
|
"hint": "Şîfreya we herî kêm heşt tîpan hewce dike"
|
||||||
|
},
|
||||||
|
"invite": {
|
||||||
|
"registration_user_invite_request": "Tu çima dixwazî beşdar bibî?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"item": {
|
||||||
|
"username": "Navê bikarhêner",
|
||||||
|
"email": "E-name",
|
||||||
|
"password": "Şîfre",
|
||||||
|
"agreement": "Lihevhatin",
|
||||||
|
"locale": "Herêm",
|
||||||
|
"reason": "Sedem"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"blocked": "%s peydekerê e-nameya bêdestûr dihewîne",
|
||||||
|
"unreachable": "%s xuya nake",
|
||||||
|
"taken": "%s jixwe tê bikaranîn",
|
||||||
|
"reserved": "%s peyveke mifteya veqetandî ye",
|
||||||
|
"accepted": "%s divê were qebûlkirin",
|
||||||
|
"blank": "%s pêwist e",
|
||||||
|
"invalid": "%s ne derbasdar e",
|
||||||
|
"too_long": "%s gelekî dirêj e",
|
||||||
|
"too_short": "%s pir kurt e",
|
||||||
|
"inclusion": "%s nirxeke ku tê destekirin nîn e"
|
||||||
|
},
|
||||||
|
"special": {
|
||||||
|
"username_invalid": "Navê bikarhêner divê tenê tîpên alfanumerîk û binxet hebe",
|
||||||
|
"username_too_long": "Navê bikarhêner pir dirêj e (ji 30 tîpan dirêjtir nabe)",
|
||||||
|
"email_invalid": "Ev ne navnîşana e-nameyek derbasdar e",
|
||||||
|
"password_too_short": "Şîfre pir kurt e (divê herî kêm 8 tîpan be)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"server_rules": {
|
||||||
|
"title": "Hin qaîdeyên bingehîn.",
|
||||||
|
"subtitle": "Ev rêzik ji aliyê rêvebirên %s ve tên sazkirin.",
|
||||||
|
"prompt": "Bi berdewamî, hûn ji bo %s di bin şertên polîtîkaya xizmet û nepenîtiyê da ne.",
|
||||||
|
"terms_of_service": "şert û mercên xizmetê",
|
||||||
|
"privacy_policy": "polîtîkaya nepenîtiyê",
|
||||||
|
"button": {
|
||||||
|
"confirm": "Ez tev dibim"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"confirm_email": {
|
||||||
|
"title": "Tiştekî dawî.",
|
||||||
|
"subtitle": "Me tenê e-nameyek ji %s re şand,\ngirêdanê bitikne da ku ajimêra xwe bidî piştrastkirin.",
|
||||||
|
"button": {
|
||||||
|
"open_email_app": "Sepana e-nameyê veke",
|
||||||
|
"dont_receive_email": "Min hîç e-nameyeke nesitand"
|
||||||
|
},
|
||||||
|
"dont_receive_email": {
|
||||||
|
"title": "E-nameyê xwe kontrol bike",
|
||||||
|
"description": "Kontrol bike ka navnîşana e-nameya te rast e û her wiha peldanka xwe ya spam.",
|
||||||
|
"resend_email": "E-namyê yê dîsa bişîne"
|
||||||
|
},
|
||||||
|
"open_email_app": {
|
||||||
|
"title": "Nameyên xwe yên wergirtî kontrol bike.",
|
||||||
|
"description": "Me tenê ji te re e-nameyek şand. Heke nehatiye peldanka xwe ya spamê kontrol bike.",
|
||||||
|
"mail": "E-name",
|
||||||
|
"open_email_client": "Rajegirê e-nameyê veke"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"home_timeline": {
|
||||||
|
"title": "Serrûpel",
|
||||||
|
"navigation_bar_state": {
|
||||||
|
"offline": "Derhêl",
|
||||||
|
"new_posts": "Şandiyên nû bibîne",
|
||||||
|
"published": "Hate weşandin!",
|
||||||
|
"Publishing": "Şandî tê weşandin..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"suggestion_account": {
|
||||||
|
"title": "Kesên bo ku bişopînî bibîne",
|
||||||
|
"follow_explain": "Gava tu kesekî dişopînî, tu yê şandiyê wan di serrûpelê de bibîne."
|
||||||
|
},
|
||||||
|
"compose": {
|
||||||
|
"title": {
|
||||||
|
"new_post": "Şandiya nû",
|
||||||
|
"new_reply": "Bersiva nû"
|
||||||
|
},
|
||||||
|
"media_selection": {
|
||||||
|
"camera": "Wêne bikişîne",
|
||||||
|
"photo_library": "Wênegeh",
|
||||||
|
"browse": "Bigere"
|
||||||
|
},
|
||||||
|
"content_input_placeholder": "Tiştê ku di hişê te de ye binivîsin an jî pêve bike",
|
||||||
|
"compose_action": "Biweşîne",
|
||||||
|
"replying_to_user": "bersiv bide %s",
|
||||||
|
"attachment": {
|
||||||
|
"photo": "wêne",
|
||||||
|
"video": "vîdyo",
|
||||||
|
"attachment_broken": "Ev %s naxebite û nayê barkirin\n li ser Mastodon.",
|
||||||
|
"description_photo": "Wêneyê ji bo kêmbînên dîtbar bide nasîn...",
|
||||||
|
"description_video": "Vîdyoyê ji bo kêmbînên dîtbar bide nasîn..."
|
||||||
|
},
|
||||||
|
"poll": {
|
||||||
|
"duration_time": "Dirêjî: %s",
|
||||||
|
"thirty_minutes": "30 xulek",
|
||||||
|
"one_hour": "1 Demjimêr",
|
||||||
|
"six_hours": "6 Demjimêr",
|
||||||
|
"one_day": "1 Roj",
|
||||||
|
"three_days": "3 Roj",
|
||||||
|
"seven_days": "7 Roj",
|
||||||
|
"option_number": "Vebijêrk %ld"
|
||||||
|
},
|
||||||
|
"content_warning": {
|
||||||
|
"placeholder": "Li vir hişyariyek hûrgilî binivîsine..."
|
||||||
|
},
|
||||||
|
"visibility": {
|
||||||
|
"public": "Gelemperî",
|
||||||
|
"unlisted": "Nerêzokkirî",
|
||||||
|
"private": "Tenê şopîneran",
|
||||||
|
"direct": "Tenê mirovên ku min qalkirî"
|
||||||
|
},
|
||||||
|
"auto_complete": {
|
||||||
|
"space_to_add": "Bicîhkirinê tevlî bike"
|
||||||
|
},
|
||||||
|
"accessibility": {
|
||||||
|
"append_attachment": "Pêvek tevlî bike",
|
||||||
|
"append_poll": "Rapirsî tevlî bike",
|
||||||
|
"remove_poll": "Rapirsî rake",
|
||||||
|
"custom_emoji_picker": "Hilbijêrê emojî yên kesanekirî",
|
||||||
|
"enable_content_warning": "Hişyariya naverokê neçalak bike",
|
||||||
|
"disable_content_warning": "Hişyariya naverokê neçalak bike",
|
||||||
|
"post_visibility_menu": "Menuya Xuyabûna Şandiyê"
|
||||||
|
},
|
||||||
|
"keyboard": {
|
||||||
|
"discard_post": "Şandî bihelîne",
|
||||||
|
"publish_post": "Şandiye bide weşan",
|
||||||
|
"toggle_poll": "Anketê veke/bigire",
|
||||||
|
"toggle_content_warning": "Hişyariya naverokê veke/bigire",
|
||||||
|
"append_attachment_entry": "Pêvek lê zêde bike - %s",
|
||||||
|
"select_visibility_entry": "Xuyanîbûn hilbijêre - %s"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"dashboard": {
|
||||||
|
"posts": "şandîyan",
|
||||||
|
"following": "dişopîne",
|
||||||
|
"followers": "şopîneran"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"add_row": "Rêzê lê zêde bike",
|
||||||
|
"placeholder": {
|
||||||
|
"label": "Nîşan",
|
||||||
|
"content": "Naverok"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"segmented_control": {
|
||||||
|
"posts": "Şandîyan",
|
||||||
|
"replies": "Bersivan",
|
||||||
|
"media": "Medya"
|
||||||
|
},
|
||||||
|
"relationship_action_alert": {
|
||||||
|
"confirm_unmute_user": {
|
||||||
|
"title": "Hesabê ji bê deng rake",
|
||||||
|
"message": "Ji bo vekirina bê dengkirinê bipejirin %s"
|
||||||
|
},
|
||||||
|
"confirm_unblock_usre": {
|
||||||
|
"title": "Hesabê ji bloke rake",
|
||||||
|
"message": "Ji bo rakirina blokê bipejirin %s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Şopîner ji rajekerên din nayê dîtin."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Şopandin ji rajekerên din nayê dîtin."
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"title": "Bigere",
|
||||||
|
"search_bar": {
|
||||||
|
"placeholder": "Li etîketan û bikarhêneran bigerin",
|
||||||
|
"cancel": "Betal kirin"
|
||||||
|
},
|
||||||
|
"recommend": {
|
||||||
|
"button_text": "Hemûyé bibîne",
|
||||||
|
"hash_tag": {
|
||||||
|
"title": "Trend li ser Mastodon",
|
||||||
|
"description": "Etîketên ku pir balê dikişînin",
|
||||||
|
"people_talking": "%s kes diaxivin"
|
||||||
|
},
|
||||||
|
"accounts": {
|
||||||
|
"title": "Hesabên ku hûn dikarin hez bikin",
|
||||||
|
"description": "Dibe ku tu bixwazî van hesaban bişopînî",
|
||||||
|
"follow": "Bişopîne"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"searching": {
|
||||||
|
"segment": {
|
||||||
|
"all": "Hemû",
|
||||||
|
"people": "Mirov",
|
||||||
|
"hashtags": "Etîketan",
|
||||||
|
"posts": "Şandîyan"
|
||||||
|
},
|
||||||
|
"empty_state": {
|
||||||
|
"no_results": "Encam tune"
|
||||||
|
},
|
||||||
|
"recent_search": "Lêgerînên dawî",
|
||||||
|
"clear": "Paqij bike"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"favorite": {
|
||||||
|
"title": "Bijareyên te"
|
||||||
|
},
|
||||||
|
"notification": {
|
||||||
|
"title": {
|
||||||
|
"Everything": "Her tişt",
|
||||||
|
"Mentions": "Behs"
|
||||||
|
},
|
||||||
|
"user_followed_you": "%s te şopand",
|
||||||
|
"user_favorited your post": "%s posta we bijarte",
|
||||||
|
"user_reblogged_your_post": "%s posta we ji nû ve tomar kir",
|
||||||
|
"user_mentioned_you": "%s behsa te kir",
|
||||||
|
"user_requested_to_follow_you": "%s daxwaza şopandina te kir",
|
||||||
|
"user_your_poll_has_ended": "%s Anketa te qediya",
|
||||||
|
"keyobard": {
|
||||||
|
"show_everything": "Her tiştî nîşan bide",
|
||||||
|
"show_mentions": "Behskirîya nîşan bike"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thread": {
|
||||||
|
"back_title": "Şandî",
|
||||||
|
"title": "Şandî ji %s"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Sazkarî",
|
||||||
|
"section": {
|
||||||
|
"appearance": {
|
||||||
|
"title": "Xuyang",
|
||||||
|
"automatic": "Xweber",
|
||||||
|
"light": "Her dem ronî",
|
||||||
|
"dark": "Her dem tarî"
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"title": "Agahdarî",
|
||||||
|
"favorites": "Şandiyên min hez kir",
|
||||||
|
"follows": "Min şopand",
|
||||||
|
"boosts": "Şandiya min ji nû ve binivîsine",
|
||||||
|
"mentions": "Qale min kir",
|
||||||
|
"trigger": {
|
||||||
|
"anyone": "her kes",
|
||||||
|
"follower": "şopînerek",
|
||||||
|
"follow": "her kesê ku dişopînim",
|
||||||
|
"noone": "ne yek",
|
||||||
|
"title": "Min agahdar bike gava"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"preference": {
|
||||||
|
"title": "Hilbijarte",
|
||||||
|
"true_black_dark_mode": "Moda tarî ya reş a rastîn",
|
||||||
|
"disable_avatar_animation": "Avatarên anîmasyonî neçalak bike",
|
||||||
|
"disable_emoji_animation": "Emojiyên anîmasyonî neçalak bike",
|
||||||
|
"using_default_browser": "Ji bo vekirina girêdanan geroka berdest bi kar bîne"
|
||||||
|
},
|
||||||
|
"boring_zone": {
|
||||||
|
"title": "Devera acizker",
|
||||||
|
"account_settings": "Sazkariyên ajimêr",
|
||||||
|
"terms": "Mercên bikaranînê",
|
||||||
|
"privacy": "Polîtikaya nihêniyê"
|
||||||
|
},
|
||||||
|
"spicy_zone": {
|
||||||
|
"title": "Devera germ",
|
||||||
|
"clear": "Pêşbîra medyayê pak bike",
|
||||||
|
"signout": "Derkeve"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"mastodon_description": "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di %s (%s) de"
|
||||||
|
},
|
||||||
|
"keyboard": {
|
||||||
|
"close_settings_window": "Sazkariyên çarçoveyê bigire"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"report": {
|
||||||
|
"title": "%s ragihîne",
|
||||||
|
"step1": "Gav 1 ji 2",
|
||||||
|
"step2": "Gav 2 ji 2",
|
||||||
|
"content1": "Şandiyên din hene ku tu dixwazî tevlî ragihandinê bikî?",
|
||||||
|
"content2": "Derbarê vê ragihandinê de tiştek heye ku divê çavdêr bizanin?",
|
||||||
|
"send": "Ragihandinê bişîne",
|
||||||
|
"skip_to_send": "Bêyî şirove bişîne",
|
||||||
|
"text_placeholder": "Şiroveyên daxwazkirê binivîsine an jî pê ve bike"
|
||||||
|
},
|
||||||
|
"preview": {
|
||||||
|
"keyboard": {
|
||||||
|
"close_preview": "Pêşdîtin bigire",
|
||||||
|
"show_next": "A pêş nîşan bide",
|
||||||
|
"show_previous": "A paş nîşan bide"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"account_list": {
|
||||||
|
"tab_bar_hint": "Profîla hilbijartî ya niha: %s. Du caran bitikîne û paşê dest bide ser da ku guhêrbara ajimêr were nîşandan",
|
||||||
|
"dismiss_account_switcher": "Guherkera ajimêrê paş guh bike",
|
||||||
|
"add_account": "Ajimêr tevlî bike"
|
||||||
|
},
|
||||||
|
"wizard": {
|
||||||
|
"new_in_mastodon": "Nû di Mastodon de",
|
||||||
|
"multiple_account_switch_intro_description": "Dest bide ser bişkoja profîlê da ku di navbera gelek ajimêrann de biguherînî.",
|
||||||
|
"accessibility_hint": "Du caran bitikîne da ku çarçoveyahilpekok ji holê rakî"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"NSCameraUsageDescription": "Bo kişandina wêneyê ji bo rewşa şandiyan tê bikaranîn",
|
||||||
|
"NSPhotoLibraryAddUsageDescription": "Ji bo tomarkirina wêneyê di pirtûkxaneya wêneyan de tê bikaranîn",
|
||||||
|
"NewPostShortcutItemTitle": "Şandiya nû",
|
||||||
|
"SearchShortcutItemTitle": "Bigere"
|
||||||
|
}
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "완료",
|
"done": "완료",
|
||||||
"confirm": "확인",
|
"confirm": "확인",
|
||||||
"continue": "계속",
|
"continue": "계속",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "취소",
|
"cancel": "취소",
|
||||||
"discard": "버리기",
|
"discard": "버리기",
|
||||||
"try_again": "다시 시도",
|
"try_again": "다시 시도",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "검색",
|
"title": "검색",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Klaar",
|
"done": "Klaar",
|
||||||
"confirm": "Bevestigen",
|
"confirm": "Bevestigen",
|
||||||
"continue": "Doorgaan",
|
"continue": "Doorgaan",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Annuleren",
|
"cancel": "Annuleren",
|
||||||
"discard": "Weggooien",
|
"discard": "Weggooien",
|
||||||
"try_again": "Probeer Opnieuw",
|
"try_again": "Probeer Opnieuw",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Zoeken",
|
"title": "Zoeken",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Готово",
|
"done": "Готово",
|
||||||
"confirm": "Подтвердить",
|
"confirm": "Подтвердить",
|
||||||
"continue": "Продолжить",
|
"continue": "Продолжить",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Отмена",
|
"cancel": "Отмена",
|
||||||
"discard": "Отмена",
|
"discard": "Отмена",
|
||||||
"try_again": "Попробовать снова",
|
"try_again": "Попробовать снова",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Поиск",
|
"title": "Поиск",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Fortsätt",
|
"continue": "Fortsätt",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Avbryt",
|
"cancel": "Avbryt",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Försök igen",
|
"try_again": "Försök igen",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Fortsätt",
|
"continue": "Fortsätt",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Avbryt",
|
"cancel": "Avbryt",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Försök igen",
|
"try_again": "Försök igen",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "เสร็จสิ้น",
|
"done": "เสร็จสิ้น",
|
||||||
"confirm": "ยืนยัน",
|
"confirm": "ยืนยัน",
|
||||||
"continue": "ดำเนินการต่อ",
|
"continue": "ดำเนินการต่อ",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "ยกเลิก",
|
"cancel": "ยกเลิก",
|
||||||
"discard": "ละทิ้ง",
|
"discard": "ละทิ้ง",
|
||||||
"try_again": "ลองอีกครั้ง",
|
"try_again": "ลองอีกครั้ง",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "ค้นหา",
|
"title": "ค้นหา",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "完成",
|
"done": "完成",
|
||||||
"confirm": "确认",
|
"confirm": "确认",
|
||||||
"continue": "继续",
|
"continue": "继续",
|
||||||
|
"compose": "撰写",
|
||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"discard": "放弃",
|
"discard": "放弃",
|
||||||
"try_again": "再试一次",
|
"try_again": "再试一次",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "不会显示来自其它服务器的关注者"
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "不会显示来自其它服务器的关注"
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "搜索",
|
"title": "搜索",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
|
"compose": "Compose",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"discard": "Discard",
|
"discard": "Discard",
|
||||||
"try_again": "Try Again",
|
"try_again": "Try Again",
|
||||||
|
@ -413,6 +414,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"follower": {
|
||||||
|
"footer": "Followers from other servers are not displayed."
|
||||||
|
},
|
||||||
|
"following": {
|
||||||
|
"footer": "Follows from other servers are not displayed."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"title": "Search",
|
"title": "Search",
|
||||||
"search_bar": {
|
"search_bar": {
|
||||||
|
|
|
@ -296,6 +296,11 @@
|
||||||
DB59F10425EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F10325EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift */; };
|
DB59F10425EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F10325EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift */; };
|
||||||
DB59F10E25EF724F001F1DAB /* APIService+Poll.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F10D25EF724F001F1DAB /* APIService+Poll.swift */; };
|
DB59F10E25EF724F001F1DAB /* APIService+Poll.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F10D25EF724F001F1DAB /* APIService+Poll.swift */; };
|
||||||
DB59F11825EFA35B001F1DAB /* StripProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F11725EFA35B001F1DAB /* StripProgressView.swift */; };
|
DB59F11825EFA35B001F1DAB /* StripProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F11725EFA35B001F1DAB /* StripProgressView.swift */; };
|
||||||
|
DB5B7295273112B100081888 /* FollowingListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B7294273112B100081888 /* FollowingListViewController.swift */; };
|
||||||
|
DB5B7298273112C800081888 /* FollowingListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B7297273112C800081888 /* FollowingListViewModel.swift */; };
|
||||||
|
DB5B729A2731137900081888 /* FollowingListViewController+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B72992731137900081888 /* FollowingListViewController+Provider.swift */; };
|
||||||
|
DB5B729C273113C200081888 /* FollowingListViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B729B273113C200081888 /* FollowingListViewModel+Diffable.swift */; };
|
||||||
|
DB5B729E273113F300081888 /* FollowingListViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5B729D273113F300081888 /* FollowingListViewModel+State.swift */; };
|
||||||
DB6180DD263918E30018D199 /* MediaPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180DC263918E30018D199 /* MediaPreviewViewController.swift */; };
|
DB6180DD263918E30018D199 /* MediaPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180DC263918E30018D199 /* MediaPreviewViewController.swift */; };
|
||||||
DB6180E02639194B0018D199 /* MediaPreviewPagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180DF2639194B0018D199 /* MediaPreviewPagingViewController.swift */; };
|
DB6180E02639194B0018D199 /* MediaPreviewPagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180DF2639194B0018D199 /* MediaPreviewPagingViewController.swift */; };
|
||||||
DB6180E326391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180E226391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift */; };
|
DB6180E326391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180E226391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift */; };
|
||||||
|
@ -310,11 +315,13 @@
|
||||||
DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */; };
|
DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */; };
|
||||||
DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */; };
|
DB6180FA26391F2E0018D199 /* MediaPreviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */; };
|
||||||
DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */; };
|
DB63BE7F268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */; };
|
||||||
DB647C5726F1E97300F7F82C /* MainTabBarController+Wizard.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647C5626F1E97300F7F82C /* MainTabBarController+Wizard.swift */; };
|
|
||||||
DB647C5926F1EA2700F7F82C /* WizardPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647C5826F1EA2700F7F82C /* WizardPreference.swift */; };
|
DB647C5926F1EA2700F7F82C /* WizardPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647C5826F1EA2700F7F82C /* WizardPreference.swift */; };
|
||||||
DB66728C25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */; };
|
DB66728C25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */; };
|
||||||
DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.swift */; };
|
DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.swift */; };
|
||||||
DB66729C25F9F91F00D60309 /* ComposeStatusItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */; };
|
DB66729C25F9F91F00D60309 /* ComposeStatusItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */; };
|
||||||
|
DB67D08427312970006A36CF /* APIService+Following.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB67D08327312970006A36CF /* APIService+Following.swift */; };
|
||||||
|
DB67D08627312E67006A36CF /* WizardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB67D08527312E67006A36CF /* WizardViewController.swift */; };
|
||||||
|
DB67D089273256D7006A36CF /* StoreReviewPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB67D088273256D7006A36CF /* StoreReviewPreference.swift */; };
|
||||||
DB68045B2636DC6A00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; };
|
DB68045B2636DC6A00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; };
|
||||||
DB6804662636DC9000430867 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D939AB425EDD8A90076FA61 /* String.swift */; };
|
DB6804662636DC9000430867 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D939AB425EDD8A90076FA61 /* String.swift */; };
|
||||||
DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; };
|
DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; };
|
||||||
|
@ -333,6 +340,17 @@
|
||||||
DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68A06225E905E000CFDF14 /* UIApplication.swift */; };
|
DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68A06225E905E000CFDF14 /* UIApplication.swift */; };
|
||||||
DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */; };
|
DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */; };
|
||||||
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */; };
|
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */; };
|
||||||
|
DB6B74EF272FB55000C70B6E /* FollowerListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74EE272FB55000C70B6E /* FollowerListViewController.swift */; };
|
||||||
|
DB6B74F2272FB67600C70B6E /* FollowerListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74F1272FB67600C70B6E /* FollowerListViewModel.swift */; };
|
||||||
|
DB6B74F4272FBAE700C70B6E /* FollowerListViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74F3272FBAE700C70B6E /* FollowerListViewModel+Diffable.swift */; };
|
||||||
|
DB6B74F6272FBCDB00C70B6E /* FollowerListViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74F5272FBCDB00C70B6E /* FollowerListViewModel+State.swift */; };
|
||||||
|
DB6B74F8272FBFB100C70B6E /* FollowerListViewController+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74F7272FBFB100C70B6E /* FollowerListViewController+Provider.swift */; };
|
||||||
|
DB6B74FA272FC2B500C70B6E /* APIService+Follower.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74F9272FC2B500C70B6E /* APIService+Follower.swift */; };
|
||||||
|
DB6B74FC272FF55800C70B6E /* UserSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74FB272FF55800C70B6E /* UserSection.swift */; };
|
||||||
|
DB6B74FE272FF59000C70B6E /* UserItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74FD272FF59000C70B6E /* UserItem.swift */; };
|
||||||
|
DB6B7500272FF73800C70B6E /* UserTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B74FF272FF73800C70B6E /* UserTableViewCell.swift */; };
|
||||||
|
DB6B75022730060700C70B6E /* UserProviderFacade+UITableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B75012730060700C70B6E /* UserProviderFacade+UITableViewDelegate.swift */; };
|
||||||
|
DB6B750427300B4000C70B6E /* TimelineFooterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6B750327300B4000C70B6E /* TimelineFooterTableViewCell.swift */; };
|
||||||
DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */; };
|
DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */; };
|
||||||
DB6D1B3D2636857500ACB481 /* AppearancePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6D1B3C2636857500ACB481 /* AppearancePreference.swift */; };
|
DB6D1B3D2636857500ACB481 /* AppearancePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6D1B3C2636857500ACB481 /* AppearancePreference.swift */; };
|
||||||
DB6D1B44263691CF00ACB481 /* Mastodon+API+Subscriptions+Policy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6D1B43263691CF00ACB481 /* Mastodon+API+Subscriptions+Policy.swift */; };
|
DB6D1B44263691CF00ACB481 /* Mastodon+API+Subscriptions+Policy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6D1B43263691CF00ACB481 /* Mastodon+API+Subscriptions+Policy.swift */; };
|
||||||
|
@ -1099,6 +1117,11 @@
|
||||||
DB59F10325EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewCellHeightCacheableContainer.swift; sourceTree = "<group>"; };
|
DB59F10325EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewCellHeightCacheableContainer.swift; sourceTree = "<group>"; };
|
||||||
DB59F10D25EF724F001F1DAB /* APIService+Poll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Poll.swift"; sourceTree = "<group>"; };
|
DB59F10D25EF724F001F1DAB /* APIService+Poll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Poll.swift"; sourceTree = "<group>"; };
|
||||||
DB59F11725EFA35B001F1DAB /* StripProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripProgressView.swift; sourceTree = "<group>"; };
|
DB59F11725EFA35B001F1DAB /* StripProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripProgressView.swift; sourceTree = "<group>"; };
|
||||||
|
DB5B7294273112B100081888 /* FollowingListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingListViewController.swift; sourceTree = "<group>"; };
|
||||||
|
DB5B7297273112C800081888 /* FollowingListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingListViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
DB5B72992731137900081888 /* FollowingListViewController+Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowingListViewController+Provider.swift"; sourceTree = "<group>"; };
|
||||||
|
DB5B729B273113C200081888 /* FollowingListViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowingListViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||||
|
DB5B729D273113F300081888 /* FollowingListViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowingListViewModel+State.swift"; sourceTree = "<group>"; };
|
||||||
DB6180DC263918E30018D199 /* MediaPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewController.swift; sourceTree = "<group>"; };
|
DB6180DC263918E30018D199 /* MediaPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewController.swift; sourceTree = "<group>"; };
|
||||||
DB6180DF2639194B0018D199 /* MediaPreviewPagingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewPagingViewController.swift; sourceTree = "<group>"; };
|
DB6180DF2639194B0018D199 /* MediaPreviewPagingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewPagingViewController.swift; sourceTree = "<group>"; };
|
||||||
DB6180E226391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerAnimatedTransitioning.swift; sourceTree = "<group>"; };
|
DB6180E226391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerAnimatedTransitioning.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1113,11 +1136,13 @@
|
||||||
DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewingViewController.swift; sourceTree = "<group>"; };
|
DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewingViewController.swift; sourceTree = "<group>"; };
|
||||||
DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewModel.swift; sourceTree = "<group>"; };
|
DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewModel.swift; sourceTree = "<group>"; };
|
||||||
DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationViewController+StatusProvider.swift"; sourceTree = "<group>"; };
|
DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationViewController+StatusProvider.swift"; sourceTree = "<group>"; };
|
||||||
DB647C5626F1E97300F7F82C /* MainTabBarController+Wizard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainTabBarController+Wizard.swift"; sourceTree = "<group>"; };
|
|
||||||
DB647C5826F1EA2700F7F82C /* WizardPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardPreference.swift; sourceTree = "<group>"; };
|
DB647C5826F1EA2700F7F82C /* WizardPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardPreference.swift; sourceTree = "<group>"; };
|
||||||
DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ComposeViewModel+DataSource.swift"; sourceTree = "<group>"; };
|
DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ComposeViewModel+DataSource.swift"; sourceTree = "<group>"; };
|
||||||
DB66729525F9F91600D60309 /* ComposeStatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusSection.swift; sourceTree = "<group>"; };
|
DB66729525F9F91600D60309 /* ComposeStatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusSection.swift; sourceTree = "<group>"; };
|
||||||
DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = "<group>"; };
|
DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = "<group>"; };
|
||||||
|
DB67D08327312970006A36CF /* APIService+Following.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Following.swift"; sourceTree = "<group>"; };
|
||||||
|
DB67D08527312E67006A36CF /* WizardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardViewController.swift; sourceTree = "<group>"; };
|
||||||
|
DB67D088273256D7006A36CF /* StoreReviewPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreReviewPreference.swift; sourceTree = "<group>"; };
|
||||||
DB68045A2636DC6A00430867 /* MastodonNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonNotification.swift; sourceTree = "<group>"; };
|
DB68045A2636DC6A00430867 /* MastodonNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonNotification.swift; sourceTree = "<group>"; };
|
||||||
DB68047F2637CD4C00430867 /* AppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
DB68047F2637CD4C00430867 /* AppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
DB6804812637CD4C00430867 /* AppShared.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppShared.h; sourceTree = "<group>"; };
|
DB6804812637CD4C00430867 /* AppShared.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppShared.h; sourceTree = "<group>"; };
|
||||||
|
@ -1132,6 +1157,17 @@
|
||||||
DB68A06225E905E000CFDF14 /* UIApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
DB68A06225E905E000CFDF14 /* UIApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIApplication.swift; sourceTree = "<group>"; };
|
||||||
DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonAttachmentService.swift; sourceTree = "<group>"; };
|
DB6B35172601FA3400DC1E11 /* MastodonAttachmentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonAttachmentService.swift; sourceTree = "<group>"; };
|
||||||
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusAttachmentCollectionViewCell.swift; sourceTree = "<group>"; };
|
DB6B351D2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusAttachmentCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
DB6B74EE272FB55000C70B6E /* FollowerListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowerListViewController.swift; sourceTree = "<group>"; };
|
||||||
|
DB6B74F1272FB67600C70B6E /* FollowerListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowerListViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
DB6B74F3272FBAE700C70B6E /* FollowerListViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowerListViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||||
|
DB6B74F5272FBCDB00C70B6E /* FollowerListViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowerListViewModel+State.swift"; sourceTree = "<group>"; };
|
||||||
|
DB6B74F7272FBFB100C70B6E /* FollowerListViewController+Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowerListViewController+Provider.swift"; sourceTree = "<group>"; };
|
||||||
|
DB6B74F9272FC2B500C70B6E /* APIService+Follower.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Follower.swift"; sourceTree = "<group>"; };
|
||||||
|
DB6B74FB272FF55800C70B6E /* UserSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSection.swift; sourceTree = "<group>"; };
|
||||||
|
DB6B74FD272FF59000C70B6E /* UserItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserItem.swift; sourceTree = "<group>"; };
|
||||||
|
DB6B74FF272FF73800C70B6E /* UserTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
DB6B75012730060700C70B6E /* UserProviderFacade+UITableViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserProviderFacade+UITableViewDelegate.swift"; sourceTree = "<group>"; };
|
||||||
|
DB6B750327300B4000C70B6E /* TimelineFooterTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineFooterTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Error.swift"; sourceTree = "<group>"; };
|
DB6C8C0E25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Error.swift"; sourceTree = "<group>"; };
|
||||||
DB6D1B3C2636857500ACB481 /* AppearancePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePreference.swift; sourceTree = "<group>"; };
|
DB6D1B3C2636857500ACB481 /* AppearancePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearancePreference.swift; sourceTree = "<group>"; };
|
||||||
DB6D1B43263691CF00ACB481 /* Mastodon+API+Subscriptions+Policy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+API+Subscriptions+Policy.swift"; sourceTree = "<group>"; };
|
DB6D1B43263691CF00ACB481 /* Mastodon+API+Subscriptions+Policy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+API+Subscriptions+Policy.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -1365,6 +1401,11 @@
|
||||||
DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemePreference.swift; sourceTree = "<group>"; };
|
DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemePreference.swift; sourceTree = "<group>"; };
|
||||||
DBD376B1269302A4007FEC24 /* UITableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewCell.swift; sourceTree = "<group>"; };
|
DBD376B1269302A4007FEC24 /* UITableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewCell.swift; sourceTree = "<group>"; };
|
||||||
DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = "<group>"; };
|
DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = "<group>"; };
|
||||||
|
DBDC1CF9272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ku-TR"; path = "ku-TR.lproj/Intents.strings"; sourceTree = "<group>"; };
|
||||||
|
DBDC1CFA272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "ku-TR"; path = "ku-TR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||||
|
DBDC1CFB272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ku-TR"; path = "ku-TR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
|
DBDC1CFC272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ku-TR"; path = "ku-TR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
|
DBDC1CFD272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "ku-TR"; path = "ku-TR.lproj/Intents.stringsdict"; sourceTree = "<group>"; };
|
||||||
DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = "<group>"; };
|
DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = "<group>"; };
|
||||||
DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewModel.swift; sourceTree = "<group>"; };
|
DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewModel.swift; sourceTree = "<group>"; };
|
||||||
DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineHeaderTableViewCell.swift; sourceTree = "<group>"; };
|
DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineHeaderTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1861,6 +1902,7 @@
|
||||||
2D4AD8A126316CD200613EFC /* SelectedAccountSection.swift */,
|
2D4AD8A126316CD200613EFC /* SelectedAccountSection.swift */,
|
||||||
DB6D9F7C26358ED4008423CD /* SettingsSection.swift */,
|
DB6D9F7C26358ED4008423CD /* SettingsSection.swift */,
|
||||||
DBA94433265CBB5300C537E1 /* ProfileFieldSection.swift */,
|
DBA94433265CBB5300C537E1 /* ProfileFieldSection.swift */,
|
||||||
|
DB6B74FB272FF55800C70B6E /* UserSection.swift */,
|
||||||
);
|
);
|
||||||
path = Section;
|
path = Section;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1904,8 +1946,10 @@
|
||||||
2DA7D04925CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift */,
|
2DA7D04925CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift */,
|
||||||
2D32EAAB25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift */,
|
2D32EAAB25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift */,
|
||||||
DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */,
|
DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */,
|
||||||
|
DB6B750327300B4000C70B6E /* TimelineFooterTableViewCell.swift */,
|
||||||
DB02CDAA26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift */,
|
DB02CDAA26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift */,
|
||||||
DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */,
|
DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */,
|
||||||
|
DB6B74FF272FF73800C70B6E /* UserTableViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = TableviewCell;
|
path = TableviewCell;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1914,6 +1958,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
2D7631B225C159F700929FB9 /* Item.swift */,
|
2D7631B225C159F700929FB9 /* Item.swift */,
|
||||||
|
DB6B74FD272FF59000C70B6E /* UserItem.swift */,
|
||||||
2D198642261BF09500F0B013 /* SearchResultItem.swift */,
|
2D198642261BF09500F0B013 /* SearchResultItem.swift */,
|
||||||
DB4F097C26A03A5B00D62E92 /* SearchHistoryItem.swift */,
|
DB4F097C26A03A5B00D62E92 /* SearchHistoryItem.swift */,
|
||||||
2D4AD8A726316D3500613EFC /* SelectedAccountItem.swift */,
|
2D4AD8A726316D3500613EFC /* SelectedAccountItem.swift */,
|
||||||
|
@ -2284,6 +2329,8 @@
|
||||||
2D34D9D026148D9E0081BFC0 /* APIService+Recommend.swift */,
|
2D34D9D026148D9E0081BFC0 /* APIService+Recommend.swift */,
|
||||||
2D34D9DA261494120081BFC0 /* APIService+Search.swift */,
|
2D34D9DA261494120081BFC0 /* APIService+Search.swift */,
|
||||||
0F202212261351F5000C64BF /* APIService+HashtagTimeline.swift */,
|
0F202212261351F5000C64BF /* APIService+HashtagTimeline.swift */,
|
||||||
|
DB6B74F9272FC2B500C70B6E /* APIService+Follower.swift */,
|
||||||
|
DB67D08327312970006A36CF /* APIService+Following.swift */,
|
||||||
DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */,
|
DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */,
|
||||||
5B24BBE1262DB19100A9381B /* APIService+Report.swift */,
|
5B24BBE1262DB19100A9381B /* APIService+Report.swift */,
|
||||||
DBAE3F932616E28B004B8251 /* APIService+Follow.swift */,
|
DBAE3F932616E28B004B8251 /* APIService+Follow.swift */,
|
||||||
|
@ -2402,6 +2449,7 @@
|
||||||
DB1D842F26566512000346B3 /* KeyboardPreference.swift */,
|
DB1D842F26566512000346B3 /* KeyboardPreference.swift */,
|
||||||
DBCBCC0C2680B908000F5B51 /* HomeTimelinePreference.swift */,
|
DBCBCC0C2680B908000F5B51 /* HomeTimelinePreference.swift */,
|
||||||
DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */,
|
DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */,
|
||||||
|
DB67D088273256D7006A36CF /* StoreReviewPreference.swift */,
|
||||||
);
|
);
|
||||||
path = Preference;
|
path = Preference;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2421,6 +2469,18 @@
|
||||||
path = View;
|
path = View;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DB5B7296273112B400081888 /* Following */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB5B7294273112B100081888 /* FollowingListViewController.swift */,
|
||||||
|
DB5B72992731137900081888 /* FollowingListViewController+Provider.swift */,
|
||||||
|
DB5B7297273112C800081888 /* FollowingListViewModel.swift */,
|
||||||
|
DB5B729B273113C200081888 /* FollowingListViewModel+Diffable.swift */,
|
||||||
|
DB5B729D273113F300081888 /* FollowingListViewModel+State.swift */,
|
||||||
|
);
|
||||||
|
path = Following;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DB6180DE263919350018D199 /* MediaPreview */ = {
|
DB6180DE263919350018D199 /* MediaPreview */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2472,6 +2532,14 @@
|
||||||
path = Image;
|
path = Image;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DB67D08727312E6A006A36CF /* Wizard */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB67D08527312E67006A36CF /* WizardViewController.swift */,
|
||||||
|
);
|
||||||
|
path = Wizard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DB6804802637CD4C00430867 /* AppShared */ = {
|
DB6804802637CD4C00430867 /* AppShared */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2503,6 +2571,18 @@
|
||||||
path = NavigationController;
|
path = NavigationController;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DB6B74F0272FB55400C70B6E /* Follower */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DB6B74EE272FB55000C70B6E /* FollowerListViewController.swift */,
|
||||||
|
DB6B74F7272FBFB100C70B6E /* FollowerListViewController+Provider.swift */,
|
||||||
|
DB6B74F1272FB67600C70B6E /* FollowerListViewModel.swift */,
|
||||||
|
DB6B74F3272FBAE700C70B6E /* FollowerListViewModel+Diffable.swift */,
|
||||||
|
DB6B74F5272FBCDB00C70B6E /* FollowerListViewModel+State.swift */,
|
||||||
|
);
|
||||||
|
path = Follower;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DB6C8C0525F0921200AAA452 /* MastodonSDK */ = {
|
DB6C8C0525F0921200AAA452 /* MastodonSDK */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2701,7 +2781,6 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */,
|
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */,
|
||||||
DB647C5626F1E97300F7F82C /* MainTabBarController+Wizard.swift */,
|
|
||||||
);
|
);
|
||||||
path = MainTab;
|
path = MainTab;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2713,6 +2792,7 @@
|
||||||
DB6180E426391A500018D199 /* Transition */,
|
DB6180E426391A500018D199 /* Transition */,
|
||||||
DB852D1D26FB021900FC9D81 /* Root */,
|
DB852D1D26FB021900FC9D81 /* Root */,
|
||||||
DB01409B25C40BB600F9F3CF /* Onboarding */,
|
DB01409B25C40BB600F9F3CF /* Onboarding */,
|
||||||
|
DB67D08727312E6A006A36CF /* Wizard */,
|
||||||
DB9F58ED26EF435800E7BBE9 /* Account */,
|
DB9F58ED26EF435800E7BBE9 /* Account */,
|
||||||
2D38F1D325CD463600561493 /* HomeTimeline */,
|
2D38F1D325CD463600561493 /* HomeTimeline */,
|
||||||
2D76316325C14BAC00929FB9 /* PublicTimeline */,
|
2D76316325C14BAC00929FB9 /* PublicTimeline */,
|
||||||
|
@ -2857,6 +2937,8 @@
|
||||||
DBB525462611ED57002F1F29 /* Header */,
|
DBB525462611ED57002F1F29 /* Header */,
|
||||||
DBB5253B2611ECF5002F1F29 /* Timeline */,
|
DBB5253B2611ECF5002F1F29 /* Timeline */,
|
||||||
DBE3CDF1261C6B3100430CC6 /* Favorite */,
|
DBE3CDF1261C6B3100430CC6 /* Favorite */,
|
||||||
|
DB6B74F0272FB55400C70B6E /* Follower */,
|
||||||
|
DB5B7296273112B400081888 /* Following */,
|
||||||
DB9D6BFE25E4F5940051B173 /* ProfileViewController.swift */,
|
DB9D6BFE25E4F5940051B173 /* ProfileViewController.swift */,
|
||||||
DBAE3F812615DDA3004B8251 /* ProfileViewController+UserProvider.swift */,
|
DBAE3F812615DDA3004B8251 /* ProfileViewController+UserProvider.swift */,
|
||||||
DBB5255D2611F07A002F1F29 /* ProfileViewModel.swift */,
|
DBB5255D2611F07A002F1F29 /* ProfileViewModel.swift */,
|
||||||
|
@ -2977,6 +3059,7 @@
|
||||||
children = (
|
children = (
|
||||||
DBAE3F672615DD60004B8251 /* UserProvider.swift */,
|
DBAE3F672615DD60004B8251 /* UserProvider.swift */,
|
||||||
DBAE3F872615DDF4004B8251 /* UserProviderFacade.swift */,
|
DBAE3F872615DDF4004B8251 /* UserProviderFacade.swift */,
|
||||||
|
DB6B75012730060700C70B6E /* UserProviderFacade+UITableViewDelegate.swift */,
|
||||||
);
|
);
|
||||||
path = UserProvider;
|
path = UserProvider;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3530,6 +3613,7 @@
|
||||||
ru,
|
ru,
|
||||||
"gd-GB",
|
"gd-GB",
|
||||||
th,
|
th,
|
||||||
|
"ku-TR",
|
||||||
);
|
);
|
||||||
mainGroup = DB427DC925BAA00100D1B89D;
|
mainGroup = DB427DC925BAA00100D1B89D;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
|
@ -3871,6 +3955,7 @@
|
||||||
DBAE3F8E2616E0B1004B8251 /* APIService+Block.swift in Sources */,
|
DBAE3F8E2616E0B1004B8251 /* APIService+Block.swift in Sources */,
|
||||||
5DF1057F25F88A4100D6C0D4 /* TouchBlockingView.swift in Sources */,
|
5DF1057F25F88A4100D6C0D4 /* TouchBlockingView.swift in Sources */,
|
||||||
DB1D843426579931000346B3 /* TableViewControllerNavigateable.swift in Sources */,
|
DB1D843426579931000346B3 /* TableViewControllerNavigateable.swift in Sources */,
|
||||||
|
DB5B729A2731137900081888 /* FollowingListViewController+Provider.swift in Sources */,
|
||||||
0FAA0FDF25E0B57E0017CCDE /* WelcomeViewController.swift in Sources */,
|
0FAA0FDF25E0B57E0017CCDE /* WelcomeViewController.swift in Sources */,
|
||||||
2D206B8C25F6015000143C56 /* AudioPlaybackService.swift in Sources */,
|
2D206B8C25F6015000143C56 /* AudioPlaybackService.swift in Sources */,
|
||||||
2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */,
|
2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */,
|
||||||
|
@ -3882,6 +3967,7 @@
|
||||||
DB03A793272A7E5700EE37C5 /* SidebarListHeaderView.swift in Sources */,
|
DB03A793272A7E5700EE37C5 /* SidebarListHeaderView.swift in Sources */,
|
||||||
DB4FFC2B269EC39600D62E92 /* SearchToSearchDetailViewControllerAnimatedTransitioning.swift in Sources */,
|
DB4FFC2B269EC39600D62E92 /* SearchToSearchDetailViewControllerAnimatedTransitioning.swift in Sources */,
|
||||||
DBCC3B9526157E6E0045B23D /* APIService+Relationship.swift in Sources */,
|
DBCC3B9526157E6E0045B23D /* APIService+Relationship.swift in Sources */,
|
||||||
|
DB5B7298273112C800081888 /* FollowingListViewModel.swift in Sources */,
|
||||||
2D7631B325C159F700929FB9 /* Item.swift in Sources */,
|
2D7631B325C159F700929FB9 /* Item.swift in Sources */,
|
||||||
5DF1054125F886D400D6C0D4 /* VideoPlaybackService.swift in Sources */,
|
5DF1054125F886D400D6C0D4 /* VideoPlaybackService.swift in Sources */,
|
||||||
DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */,
|
DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */,
|
||||||
|
@ -3959,6 +4045,7 @@
|
||||||
DB75BF1E263C1C1B00EDBF1F /* CustomScheduler.swift in Sources */,
|
DB75BF1E263C1C1B00EDBF1F /* CustomScheduler.swift in Sources */,
|
||||||
0FAA102725E1126A0017CCDE /* MastodonPickServerViewController.swift in Sources */,
|
0FAA102725E1126A0017CCDE /* MastodonPickServerViewController.swift in Sources */,
|
||||||
DB59F0FE25EF5D96001F1DAB /* StatusProvider+UITableViewDelegate.swift in Sources */,
|
DB59F0FE25EF5D96001F1DAB /* StatusProvider+UITableViewDelegate.swift in Sources */,
|
||||||
|
DB6B74FE272FF59000C70B6E /* UserItem.swift in Sources */,
|
||||||
DB68586425E619B700F0A850 /* NSKeyValueObservation.swift in Sources */,
|
DB68586425E619B700F0A850 /* NSKeyValueObservation.swift in Sources */,
|
||||||
DBE3CE07261D6A0E00430CC6 /* FavoriteViewModel+Diffable.swift in Sources */,
|
DBE3CE07261D6A0E00430CC6 /* FavoriteViewModel+Diffable.swift in Sources */,
|
||||||
2D61335825C188A000CAE157 /* APIService+Persist+Status.swift in Sources */,
|
2D61335825C188A000CAE157 /* APIService+Persist+Status.swift in Sources */,
|
||||||
|
@ -4017,6 +4104,8 @@
|
||||||
DBE3CE01261D623D00430CC6 /* FavoriteViewModel+State.swift in Sources */,
|
DBE3CE01261D623D00430CC6 /* FavoriteViewModel+State.swift in Sources */,
|
||||||
2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */,
|
2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */,
|
||||||
2D38F1EB25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift in Sources */,
|
2D38F1EB25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift in Sources */,
|
||||||
|
DB67D089273256D7006A36CF /* StoreReviewPreference.swift in Sources */,
|
||||||
|
DB5B7295273112B100081888 /* FollowingListViewController.swift in Sources */,
|
||||||
0F202201261326E6000C64BF /* HashtagTimelineViewModel.swift in Sources */,
|
0F202201261326E6000C64BF /* HashtagTimelineViewModel.swift in Sources */,
|
||||||
DB6D9F9726367249008423CD /* SettingsViewController.swift in Sources */,
|
DB6D9F9726367249008423CD /* SettingsViewController.swift in Sources */,
|
||||||
DB4F097F26A03DA600D62E92 /* SearchHistoryFetchedResultController.swift in Sources */,
|
DB4F097F26A03DA600D62E92 /* SearchHistoryFetchedResultController.swift in Sources */,
|
||||||
|
@ -4027,8 +4116,10 @@
|
||||||
DB73BF47271199CA00781945 /* Instance.swift in Sources */,
|
DB73BF47271199CA00781945 /* Instance.swift in Sources */,
|
||||||
DB0F8150264D1E2500F2A12B /* PickServerLoaderTableViewCell.swift in Sources */,
|
DB0F8150264D1E2500F2A12B /* PickServerLoaderTableViewCell.swift in Sources */,
|
||||||
DB98337F25C9452D00AD9700 /* APIService+APIError.swift in Sources */,
|
DB98337F25C9452D00AD9700 /* APIService+APIError.swift in Sources */,
|
||||||
|
DB5B729C273113C200081888 /* FollowingListViewModel+Diffable.swift in Sources */,
|
||||||
DB9E0D6F25EE008500CFDD76 /* UIInterpolatingMotionEffect.swift in Sources */,
|
DB9E0D6F25EE008500CFDD76 /* UIInterpolatingMotionEffect.swift in Sources */,
|
||||||
DBB9759C262462E1004620BD /* ThreadMetaView.swift in Sources */,
|
DBB9759C262462E1004620BD /* ThreadMetaView.swift in Sources */,
|
||||||
|
DB5B729E273113F300081888 /* FollowingListViewModel+State.swift in Sources */,
|
||||||
2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */,
|
2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */,
|
||||||
5DDDF1A92617489F00311060 /* Mastodon+Entity+History.swift in Sources */,
|
5DDDF1A92617489F00311060 /* Mastodon+Entity+History.swift in Sources */,
|
||||||
DB59F11825EFA35B001F1DAB /* StripProgressView.swift in Sources */,
|
DB59F11825EFA35B001F1DAB /* StripProgressView.swift in Sources */,
|
||||||
|
@ -4049,6 +4140,7 @@
|
||||||
2D82B9FF25E7863200E36F0F /* OnboardingViewControllerAppearance.swift in Sources */,
|
2D82B9FF25E7863200E36F0F /* OnboardingViewControllerAppearance.swift in Sources */,
|
||||||
5DF1054725F8870E00D6C0D4 /* VideoPlayerViewModel.swift in Sources */,
|
5DF1054725F8870E00D6C0D4 /* VideoPlayerViewModel.swift in Sources */,
|
||||||
DB73BF43271192BB00781945 /* InstanceService.swift in Sources */,
|
DB73BF43271192BB00781945 /* InstanceService.swift in Sources */,
|
||||||
|
DB67D08427312970006A36CF /* APIService+Following.swift in Sources */,
|
||||||
DBA9443A265CC0FC00C537E1 /* Fields.swift in Sources */,
|
DBA9443A265CC0FC00C537E1 /* Fields.swift in Sources */,
|
||||||
2DE0FAC12615F04D00CDF649 /* RecommendHashTagSection.swift in Sources */,
|
2DE0FAC12615F04D00CDF649 /* RecommendHashTagSection.swift in Sources */,
|
||||||
DBA5E7A5263BD28C004598BB /* ContextMenuImagePreviewViewModel.swift in Sources */,
|
DBA5E7A5263BD28C004598BB /* ContextMenuImagePreviewViewModel.swift in Sources */,
|
||||||
|
@ -4088,6 +4180,9 @@
|
||||||
DB9A486C26032AC1008B817C /* AttachmentContainerView+EmptyStateView.swift in Sources */,
|
DB9A486C26032AC1008B817C /* AttachmentContainerView+EmptyStateView.swift in Sources */,
|
||||||
5D0393902612D259007FE196 /* WebViewController.swift in Sources */,
|
5D0393902612D259007FE196 /* WebViewController.swift in Sources */,
|
||||||
DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */,
|
DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */,
|
||||||
|
DB6B74FA272FC2B500C70B6E /* APIService+Follower.swift in Sources */,
|
||||||
|
DB6B74F4272FBAE700C70B6E /* FollowerListViewModel+Diffable.swift in Sources */,
|
||||||
|
DB6B74F2272FB67600C70B6E /* FollowerListViewModel.swift in Sources */,
|
||||||
DB44767B260B3B8C00B66B82 /* CustomEmojiPickerInputView.swift in Sources */,
|
DB44767B260B3B8C00B66B82 /* CustomEmojiPickerInputView.swift in Sources */,
|
||||||
0F20222D261457EE000C64BF /* HashtagTimelineViewModel+LoadOldestState.swift in Sources */,
|
0F20222D261457EE000C64BF /* HashtagTimelineViewModel+LoadOldestState.swift in Sources */,
|
||||||
DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */,
|
DB0009A626AEE5DC009B9D2D /* Intents.intentdefinition in Sources */,
|
||||||
|
@ -4100,6 +4195,7 @@
|
||||||
DB35FC1F2612F1D9006193C9 /* ProfileRelationshipActionButton.swift in Sources */,
|
DB35FC1F2612F1D9006193C9 /* ProfileRelationshipActionButton.swift in Sources */,
|
||||||
DBC7A672260C897100E57475 /* StatusContentWarningEditorView.swift in Sources */,
|
DBC7A672260C897100E57475 /* StatusContentWarningEditorView.swift in Sources */,
|
||||||
DB3667A6268AE2620027D07F /* ComposeStatusPollSection.swift in Sources */,
|
DB3667A6268AE2620027D07F /* ComposeStatusPollSection.swift in Sources */,
|
||||||
|
DB6B750427300B4000C70B6E /* TimelineFooterTableViewCell.swift in Sources */,
|
||||||
DB59F10E25EF724F001F1DAB /* APIService+Poll.swift in Sources */,
|
DB59F10E25EF724F001F1DAB /* APIService+Poll.swift in Sources */,
|
||||||
DB852D1F26FB037800FC9D81 /* SidebarViewModel.swift in Sources */,
|
DB852D1F26FB037800FC9D81 /* SidebarViewModel.swift in Sources */,
|
||||||
DB47229725F9EFAD00DA7F53 /* NSManagedObjectContext.swift in Sources */,
|
DB47229725F9EFAD00DA7F53 /* NSManagedObjectContext.swift in Sources */,
|
||||||
|
@ -4116,6 +4212,7 @@
|
||||||
DBF156E42702DB3F00EC00B7 /* HandleTapAction.swift in Sources */,
|
DBF156E42702DB3F00EC00B7 /* HandleTapAction.swift in Sources */,
|
||||||
DB023295267F0AB800031745 /* ASMetaEditableTextNode.swift in Sources */,
|
DB023295267F0AB800031745 /* ASMetaEditableTextNode.swift in Sources */,
|
||||||
2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */,
|
2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */,
|
||||||
|
DB6B74F6272FBCDB00C70B6E /* FollowerListViewModel+State.swift in Sources */,
|
||||||
DB4F096C269EFA2000D62E92 /* SearchResultViewController+StatusProvider.swift in Sources */,
|
DB4F096C269EFA2000D62E92 /* SearchResultViewController+StatusProvider.swift in Sources */,
|
||||||
DB87D4452609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift in Sources */,
|
DB87D4452609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift in Sources */,
|
||||||
DB9F58EF26EF491E00E7BBE9 /* AccountListViewModel.swift in Sources */,
|
DB9F58EF26EF491E00E7BBE9 /* AccountListViewModel.swift in Sources */,
|
||||||
|
@ -4133,6 +4230,7 @@
|
||||||
DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */,
|
DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */,
|
||||||
DB73BF4B27140C0800781945 /* UITableViewDiffableDataSource.swift in Sources */,
|
DB73BF4B27140C0800781945 /* UITableViewDiffableDataSource.swift in Sources */,
|
||||||
DBB525642612C988002F1F29 /* MeProfileViewModel.swift in Sources */,
|
DBB525642612C988002F1F29 /* MeProfileViewModel.swift in Sources */,
|
||||||
|
DB6B74EF272FB55000C70B6E /* FollowerListViewController.swift in Sources */,
|
||||||
5BB04FE9262EFC300043BFF6 /* ReportedStatusTableviewCell.swift in Sources */,
|
5BB04FE9262EFC300043BFF6 /* ReportedStatusTableviewCell.swift in Sources */,
|
||||||
DBAE3F822615DDA3004B8251 /* ProfileViewController+UserProvider.swift in Sources */,
|
DBAE3F822615DDA3004B8251 /* ProfileViewController+UserProvider.swift in Sources */,
|
||||||
DBBC24C426A544B900398BB9 /* Theme.swift in Sources */,
|
DBBC24C426A544B900398BB9 /* Theme.swift in Sources */,
|
||||||
|
@ -4174,6 +4272,7 @@
|
||||||
DB49A63D25FF609300B98345 /* PlayerContainerView+MediaTypeIndicotorView.swift in Sources */,
|
DB49A63D25FF609300B98345 /* PlayerContainerView+MediaTypeIndicotorView.swift in Sources */,
|
||||||
DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */,
|
DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */,
|
||||||
DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */,
|
DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */,
|
||||||
|
DB6B75022730060700C70B6E /* UserProviderFacade+UITableViewDelegate.swift in Sources */,
|
||||||
DB44384F25E8C1FA008912A2 /* CALayer.swift in Sources */,
|
DB44384F25E8C1FA008912A2 /* CALayer.swift in Sources */,
|
||||||
2D34D9CB261489930081BFC0 /* SearchViewController+Recommend.swift in Sources */,
|
2D34D9CB261489930081BFC0 /* SearchViewController+Recommend.swift in Sources */,
|
||||||
DB71C7CB271D5A0300BE3819 /* LineChartView.swift in Sources */,
|
DB71C7CB271D5A0300BE3819 /* LineChartView.swift in Sources */,
|
||||||
|
@ -4239,6 +4338,7 @@
|
||||||
DBE54AC62636C89F004E7C0B /* NotificationPreference.swift in Sources */,
|
DBE54AC62636C89F004E7C0B /* NotificationPreference.swift in Sources */,
|
||||||
2D5A3D2825CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift in Sources */,
|
2D5A3D2825CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift in Sources */,
|
||||||
DB98339C25C96DE600AD9700 /* APIService+Account.swift in Sources */,
|
DB98339C25C96DE600AD9700 /* APIService+Account.swift in Sources */,
|
||||||
|
DB6B74FC272FF55800C70B6E /* UserSection.swift in Sources */,
|
||||||
2DF75BA725D10E1000694EC8 /* APIService+Favorite.swift in Sources */,
|
2DF75BA725D10E1000694EC8 /* APIService+Favorite.swift in Sources */,
|
||||||
DB9D6C3825E508BE0051B173 /* Attachment.swift in Sources */,
|
DB9D6C3825E508BE0051B173 /* Attachment.swift in Sources */,
|
||||||
5DFC35DF262068D20045711D /* SearchViewController+Follow.swift in Sources */,
|
5DFC35DF262068D20045711D /* SearchViewController+Follow.swift in Sources */,
|
||||||
|
@ -4255,6 +4355,7 @@
|
||||||
0F202227261411BB000C64BF /* HashtagTimelineViewController+Provider.swift in Sources */,
|
0F202227261411BB000C64BF /* HashtagTimelineViewController+Provider.swift in Sources */,
|
||||||
2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */,
|
2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */,
|
||||||
2D76316525C14BD100929FB9 /* PublicTimelineViewController.swift in Sources */,
|
2D76316525C14BD100929FB9 /* PublicTimelineViewController.swift in Sources */,
|
||||||
|
DB6B7500272FF73800C70B6E /* UserTableViewCell.swift in Sources */,
|
||||||
DB1D842E26552C4D000346B3 /* StatusTableViewControllerNavigateable.swift in Sources */,
|
DB1D842E26552C4D000346B3 /* StatusTableViewControllerNavigateable.swift in Sources */,
|
||||||
DB938F1F2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift in Sources */,
|
DB938F1F2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift in Sources */,
|
||||||
2D69CFF425CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift in Sources */,
|
2D69CFF425CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift in Sources */,
|
||||||
|
@ -4269,6 +4370,7 @@
|
||||||
DB71FD2C25F86A5100512AE1 /* AvatarStackContainerButton.swift in Sources */,
|
DB71FD2C25F86A5100512AE1 /* AvatarStackContainerButton.swift in Sources */,
|
||||||
DB87D4512609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift in Sources */,
|
DB87D4512609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift in Sources */,
|
||||||
DBBC24C026A5443100398BB9 /* MastodonTheme.swift in Sources */,
|
DBBC24C026A5443100398BB9 /* MastodonTheme.swift in Sources */,
|
||||||
|
DB67D08627312E67006A36CF /* WizardViewController.swift in Sources */,
|
||||||
DBBC24B526A540AE00398BB9 /* AvatarConfigurableView.swift in Sources */,
|
DBBC24B526A540AE00398BB9 /* AvatarConfigurableView.swift in Sources */,
|
||||||
DB9A489026035963008B817C /* APIService+Media.swift in Sources */,
|
DB9A489026035963008B817C /* APIService+Media.swift in Sources */,
|
||||||
DBFEF07726A691FB006D7ED1 /* MastodonAuthenticationBox.swift in Sources */,
|
DBFEF07726A691FB006D7ED1 /* MastodonAuthenticationBox.swift in Sources */,
|
||||||
|
@ -4282,9 +4384,9 @@
|
||||||
DB49A62525FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift in Sources */,
|
DB49A62525FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift in Sources */,
|
||||||
DB4924E226312AB200E9DB22 /* NotificationService.swift in Sources */,
|
DB4924E226312AB200E9DB22 /* NotificationService.swift in Sources */,
|
||||||
DB6D9F6F2635807F008423CD /* Setting.swift in Sources */,
|
DB6D9F6F2635807F008423CD /* Setting.swift in Sources */,
|
||||||
DB647C5726F1E97300F7F82C /* MainTabBarController+Wizard.swift in Sources */,
|
|
||||||
DB6F5E38264E994A009108F4 /* AutoCompleteTopChevronView.swift in Sources */,
|
DB6F5E38264E994A009108F4 /* AutoCompleteTopChevronView.swift in Sources */,
|
||||||
DBB525412611ED54002F1F29 /* ProfileHeaderViewController.swift in Sources */,
|
DBB525412611ED54002F1F29 /* ProfileHeaderViewController.swift in Sources */,
|
||||||
|
DB6B74F8272FBFB100C70B6E /* FollowerListViewController+Provider.swift in Sources */,
|
||||||
DB9D6BFF25E4F5940051B173 /* ProfileViewController.swift in Sources */,
|
DB9D6BFF25E4F5940051B173 /* ProfileViewController.swift in Sources */,
|
||||||
DB4932B326F2054200EF46D4 /* CircleAvatarButton.swift in Sources */,
|
DB4932B326F2054200EF46D4 /* CircleAvatarButton.swift in Sources */,
|
||||||
0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */,
|
0FB3D30825E524C600AAD544 /* PickServerCategoriesCell.swift in Sources */,
|
||||||
|
@ -4560,6 +4662,7 @@
|
||||||
DB4B777F26CA4EFA00B087B3 /* ru */,
|
DB4B777F26CA4EFA00B087B3 /* ru */,
|
||||||
DB4B778426CA500E00B087B3 /* gd-GB */,
|
DB4B778426CA500E00B087B3 /* gd-GB */,
|
||||||
DB4B779226CA50BA00B087B3 /* th */,
|
DB4B779226CA50BA00B087B3 /* th */,
|
||||||
|
DBDC1CF9272C0FD600055C3D /* ku-TR */,
|
||||||
);
|
);
|
||||||
name = Intents.intentdefinition;
|
name = Intents.intentdefinition;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4580,6 +4683,7 @@
|
||||||
DB4B778226CA4EFA00B087B3 /* ru */,
|
DB4B778226CA4EFA00B087B3 /* ru */,
|
||||||
DB4B778726CA500E00B087B3 /* gd-GB */,
|
DB4B778726CA500E00B087B3 /* gd-GB */,
|
||||||
DB4B779526CA50BA00B087B3 /* th */,
|
DB4B779526CA50BA00B087B3 /* th */,
|
||||||
|
DBDC1CFC272C0FD600055C3D /* ku-TR */,
|
||||||
);
|
);
|
||||||
name = InfoPlist.strings;
|
name = InfoPlist.strings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4600,6 +4704,7 @@
|
||||||
DB4B778126CA4EFA00B087B3 /* ru */,
|
DB4B778126CA4EFA00B087B3 /* ru */,
|
||||||
DB4B778626CA500E00B087B3 /* gd-GB */,
|
DB4B778626CA500E00B087B3 /* gd-GB */,
|
||||||
DB4B779426CA50BA00B087B3 /* th */,
|
DB4B779426CA50BA00B087B3 /* th */,
|
||||||
|
DBDC1CFB272C0FD600055C3D /* ku-TR */,
|
||||||
);
|
);
|
||||||
name = Localizable.strings;
|
name = Localizable.strings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4636,6 +4741,7 @@
|
||||||
DB4B778026CA4EFA00B087B3 /* ru */,
|
DB4B778026CA4EFA00B087B3 /* ru */,
|
||||||
DB4B778526CA500E00B087B3 /* gd-GB */,
|
DB4B778526CA500E00B087B3 /* gd-GB */,
|
||||||
DB4B779326CA50BA00B087B3 /* th */,
|
DB4B779326CA50BA00B087B3 /* th */,
|
||||||
|
DBDC1CFA272C0FD600055C3D /* ku-TR */,
|
||||||
);
|
);
|
||||||
name = Localizable.stringsdict;
|
name = Localizable.stringsdict;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4656,6 +4762,7 @@
|
||||||
DB4B779026CA504900B087B3 /* fr */,
|
DB4B779026CA504900B087B3 /* fr */,
|
||||||
DB4B779126CA504A00B087B3 /* ja */,
|
DB4B779126CA504A00B087B3 /* ja */,
|
||||||
DB4B779626CA50BA00B087B3 /* th */,
|
DB4B779626CA50BA00B087B3 /* th */,
|
||||||
|
DBDC1CFD272C0FD600055C3D /* ku-TR */,
|
||||||
);
|
);
|
||||||
name = Intents.stringsdict;
|
name = Intents.stringsdict;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4800,7 +4907,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = Mastodon/Info.plist;
|
INFOPLIST_FILE = Mastodon/Info.plist;
|
||||||
|
@ -4829,7 +4936,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = Mastodon/Info.plist;
|
INFOPLIST_FILE = Mastodon/Info.plist;
|
||||||
|
@ -4937,11 +5044,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = AppShared/Info.plist;
|
INFOPLIST_FILE = AppShared/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -4968,11 +5075,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = AppShared/Info.plist;
|
INFOPLIST_FILE = AppShared/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -4997,11 +5104,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -5027,11 +5134,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -5094,7 +5201,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5119,7 +5226,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5144,7 +5251,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5169,7 +5276,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
INFOPLIST_FILE = MastodonIntent/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5194,7 +5301,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5219,7 +5326,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5244,7 +5351,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5269,7 +5376,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
INFOPLIST_FILE = ShareActionExtension/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5360,7 +5467,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = Mastodon/Info.plist;
|
INFOPLIST_FILE = Mastodon/Info.plist;
|
||||||
|
@ -5427,11 +5534,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -5476,7 +5583,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = NotificationService/Info.plist;
|
INFOPLIST_FILE = NotificationService/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5501,11 +5608,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = AppShared/Info.plist;
|
INFOPLIST_FILE = AppShared/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -5597,7 +5704,7 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = Mastodon/Info.plist;
|
INFOPLIST_FILE = Mastodon/Info.plist;
|
||||||
|
@ -5664,11 +5771,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
INFOPLIST_FILE = CoreDataStack/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -5713,7 +5820,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = NotificationService/Info.plist;
|
INFOPLIST_FILE = NotificationService/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5738,11 +5845,11 @@
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 79;
|
DYLIB_CURRENT_VERSION = 83;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = AppShared/Info.plist;
|
INFOPLIST_FILE = AppShared/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
@ -5768,7 +5875,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = NotificationService/Info.plist;
|
INFOPLIST_FILE = NotificationService/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
@ -5792,7 +5899,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 79;
|
CURRENT_PROJECT_VERSION = 83;
|
||||||
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
DEVELOPMENT_TEAM = 5Z4GVSS33P;
|
||||||
INFOPLIST_FILE = NotificationService/Info.plist;
|
INFOPLIST_FILE = NotificationService/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
|
|
@ -216,15 +216,6 @@
|
||||||
"revision": "dad97167bf1be16aeecd109130900995dd01c515",
|
"revision": "dad97167bf1be16aeecd109130900995dd01c515",
|
||||||
"version": "2.6.0"
|
"version": "2.6.0"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "UITextView+Placeholder",
|
|
||||||
"repositoryURL": "https://github.com/MainasuK/UITextView-Placeholder",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "20f513ded04a040cdf5467f0891849b1763ede3b",
|
|
||||||
"version": "1.4.1"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,6 +23,7 @@ final public class SceneCoordinator {
|
||||||
|
|
||||||
private(set) weak var tabBarController: MainTabBarController!
|
private(set) weak var tabBarController: MainTabBarController!
|
||||||
private(set) weak var splitViewController: RootSplitViewController?
|
private(set) weak var splitViewController: RootSplitViewController?
|
||||||
|
private(set) var wizardViewController: WizardViewController?
|
||||||
|
|
||||||
private(set) var secondaryStackHashValues = Set<Int>()
|
private(set) var secondaryStackHashValues = Set<Int>()
|
||||||
|
|
||||||
|
@ -90,45 +91,44 @@ final public class SceneCoordinator {
|
||||||
|
|
||||||
|
|
||||||
// Delay in next run loop
|
// Delay in next run loop
|
||||||
// DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
// guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
//
|
|
||||||
// // Note:
|
// Note:
|
||||||
// // show (push) on phone or pad (compact)
|
// show (push) on phone and pad
|
||||||
// // showDetail in .secondary in UISplitViewController on pad (expand)
|
let from: UIViewController? = {
|
||||||
// let from: UIViewController? = {
|
if let splitViewController = self.splitViewController {
|
||||||
// if let splitViewController = self.splitViewController {
|
if splitViewController.compactMainTabBarViewController.topMost?.view.window != nil {
|
||||||
// if splitViewController.mainTabBarController.topMost?.view.window != nil {
|
// compact
|
||||||
// // compact
|
return splitViewController.compactMainTabBarViewController.topMost
|
||||||
// return splitViewController.mainTabBarController.topMost
|
} else {
|
||||||
// } else {
|
// expand
|
||||||
// // expand
|
return splitViewController.contentSplitViewController.mainTabBarController.topMost
|
||||||
// return splitViewController.viewController(for: .supplementary)
|
}
|
||||||
// }
|
} else {
|
||||||
// } else {
|
return self.tabBarController.topMost
|
||||||
// return self.tabBarController.topMost
|
}
|
||||||
// }
|
}()
|
||||||
// }()
|
|
||||||
//
|
// show notification related content
|
||||||
// // show notification related content
|
guard let type = Mastodon.Entity.Notification.NotificationType(rawValue: pushNotification.notificationType) else { return }
|
||||||
// guard let type = Mastodon.Entity.Notification.NotificationType(rawValue: pushNotification.notificationType) else { return }
|
let notificationID = String(pushNotification.notificationID)
|
||||||
// let notificationID = String(pushNotification.notificationID)
|
|
||||||
//
|
switch type {
|
||||||
// switch type {
|
case .follow:
|
||||||
// case .follow:
|
let profileViewModel = RemoteProfileViewModel(context: appContext, notificationID: notificationID)
|
||||||
// let profileViewModel = RemoteProfileViewModel(context: appContext, notificationID: notificationID)
|
self.present(scene: .profile(viewModel: profileViewModel), from: from, transition: .show)
|
||||||
// self.present(scene: .profile(viewModel: profileViewModel), from: from, transition: .show)
|
case .followRequest:
|
||||||
// case .followRequest:
|
// do nothing
|
||||||
// // do nothing
|
break
|
||||||
// break
|
case .mention, .reblog, .favourite, .poll, .status:
|
||||||
// case .mention, .reblog, .favourite, .poll, .status:
|
let threadViewModel = RemoteThreadViewModel(context: appContext, notificationID: notificationID)
|
||||||
// let threadViewModel = RemoteThreadViewModel(context: appContext, notificationID: notificationID)
|
self.present(scene: .thread(viewModel: threadViewModel), from: from, transition: .show)
|
||||||
// self.present(scene: .thread(viewModel: threadViewModel), from: from, transition: .show)
|
case ._other:
|
||||||
// case ._other:
|
assertionFailure()
|
||||||
// assertionFailure()
|
break
|
||||||
// break
|
}
|
||||||
// }
|
} // end DispatchQueue.main.async
|
||||||
// } // end DispatchQueue.main.async
|
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ extension SceneCoordinator {
|
||||||
case show // push
|
case show // push
|
||||||
case showDetail // replace
|
case showDetail // replace
|
||||||
case modal(animated: Bool, completion: (() -> Void)? = nil)
|
case modal(animated: Bool, completion: (() -> Void)? = nil)
|
||||||
|
case popover(sourceView: UIView)
|
||||||
case panModal
|
case panModal
|
||||||
case custom(transitioningDelegate: UIViewControllerTransitioningDelegate)
|
case custom(transitioningDelegate: UIViewControllerTransitioningDelegate)
|
||||||
case customPush
|
case customPush
|
||||||
|
@ -178,6 +179,8 @@ extension SceneCoordinator {
|
||||||
case accountList
|
case accountList
|
||||||
case profile(viewModel: ProfileViewModel)
|
case profile(viewModel: ProfileViewModel)
|
||||||
case favorite(viewModel: FavoriteViewModel)
|
case favorite(viewModel: FavoriteViewModel)
|
||||||
|
case follower(viewModel: FollowerListViewModel)
|
||||||
|
case following(viewModel: FollowingListViewModel)
|
||||||
|
|
||||||
// setting
|
// setting
|
||||||
case settings(viewModel: SettingsViewModel)
|
case settings(viewModel: SettingsViewModel)
|
||||||
|
@ -219,17 +222,34 @@ extension SceneCoordinator {
|
||||||
extension SceneCoordinator {
|
extension SceneCoordinator {
|
||||||
|
|
||||||
func setup() {
|
func setup() {
|
||||||
|
let rootViewController: UIViewController
|
||||||
switch UIDevice.current.userInterfaceIdiom {
|
switch UIDevice.current.userInterfaceIdiom {
|
||||||
case .phone:
|
case .phone:
|
||||||
let viewController = MainTabBarController(context: appContext, coordinator: self)
|
let viewController = MainTabBarController(context: appContext, coordinator: self)
|
||||||
sceneDelegate.window?.rootViewController = viewController
|
self.splitViewController = nil
|
||||||
tabBarController = viewController
|
self.tabBarController = viewController
|
||||||
|
rootViewController = viewController
|
||||||
default:
|
default:
|
||||||
let splitViewController = RootSplitViewController(context: appContext, coordinator: self)
|
let splitViewController = RootSplitViewController(context: appContext, coordinator: self)
|
||||||
self.splitViewController = splitViewController
|
self.splitViewController = splitViewController
|
||||||
self.tabBarController = splitViewController.contentSplitViewController.mainTabBarController
|
self.tabBarController = splitViewController.contentSplitViewController.mainTabBarController
|
||||||
sceneDelegate.window?.rootViewController = splitViewController
|
rootViewController = splitViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let wizardViewController = WizardViewController()
|
||||||
|
if !wizardViewController.items.isEmpty,
|
||||||
|
let delegate = rootViewController as? WizardViewControllerDelegate
|
||||||
|
{
|
||||||
|
// do not add as child view controller.
|
||||||
|
// otherwise, the tab bar controller will add as a new tab
|
||||||
|
wizardViewController.delegate = delegate
|
||||||
|
wizardViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
|
wizardViewController.view.frame = rootViewController.view.bounds
|
||||||
|
rootViewController.view.addSubview(wizardViewController.view)
|
||||||
|
self.wizardViewController = wizardViewController
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneDelegate.window?.rootViewController = rootViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupOnboardingIfNeeds(animated: Bool) {
|
func setupOnboardingIfNeeds(animated: Bool) {
|
||||||
|
@ -282,18 +302,6 @@ extension SceneCoordinator {
|
||||||
|
|
||||||
switch transition {
|
switch transition {
|
||||||
case .show:
|
case .show:
|
||||||
// if let splitViewController = splitViewController, !splitViewController.isCollapsed,
|
|
||||||
// let supplementaryViewController = splitViewController.viewController(for: .supplementary) as? UINavigationController,
|
|
||||||
// (supplementaryViewController === presentingViewController || supplementaryViewController.viewControllers.contains(presentingViewController)) ||
|
|
||||||
// (presentingViewController is UserTimelineViewController && presentingViewController.view.isDescendant(of: supplementaryViewController.view))
|
|
||||||
// {
|
|
||||||
// fallthrough
|
|
||||||
// } else {
|
|
||||||
// if secondaryStackHashValues.contains(presentingViewController.hashValue) {
|
|
||||||
// secondaryStackHashValues.insert(viewController.hashValue)
|
|
||||||
// }
|
|
||||||
// presentingViewController.show(viewController, sender: sender)
|
|
||||||
// }
|
|
||||||
presentingViewController.show(viewController, sender: sender)
|
presentingViewController.show(viewController, sender: sender)
|
||||||
case .showDetail:
|
case .showDetail:
|
||||||
secondaryStackHashValues.insert(viewController.hashValue)
|
secondaryStackHashValues.insert(viewController.hashValue)
|
||||||
|
@ -326,7 +334,10 @@ extension SceneCoordinator {
|
||||||
panModalPresentable.transitioningDelegate = PanModalPresentationDelegate.default
|
panModalPresentable.transitioningDelegate = PanModalPresentationDelegate.default
|
||||||
presentingViewController.present(panModalPresentable, animated: true, completion: nil)
|
presentingViewController.present(panModalPresentable, animated: true, completion: nil)
|
||||||
//presentingViewController.presentPanModal(panModalPresentable)
|
//presentingViewController.presentPanModal(panModalPresentable)
|
||||||
|
case .popover(let sourceView):
|
||||||
|
viewController.modalPresentationStyle = .popover
|
||||||
|
viewController.popoverPresentationController?.sourceView = sourceView
|
||||||
|
(splitViewController ?? presentingViewController)?.present(viewController, animated: true, completion: nil)
|
||||||
case .custom(let transitioningDelegate):
|
case .custom(let transitioningDelegate):
|
||||||
viewController.modalPresentationStyle = .custom
|
viewController.modalPresentationStyle = .custom
|
||||||
viewController.transitioningDelegate = transitioningDelegate
|
viewController.transitioningDelegate = transitioningDelegate
|
||||||
|
@ -358,6 +369,11 @@ extension SceneCoordinator {
|
||||||
}
|
}
|
||||||
|
|
||||||
func switchToTabBar(tab: MainTabBarController.Tab) {
|
func switchToTabBar(tab: MainTabBarController.Tab) {
|
||||||
|
splitViewController?.contentSplitViewController.currentSupplementaryTab = tab
|
||||||
|
|
||||||
|
splitViewController?.compactMainTabBarViewController.selectedIndex = tab.rawValue
|
||||||
|
splitViewController?.compactMainTabBarViewController.currentTab.value = tab
|
||||||
|
|
||||||
tabBarController.selectedIndex = tab.rawValue
|
tabBarController.selectedIndex = tab.rawValue
|
||||||
tabBarController.currentTab.value = tab
|
tabBarController.currentTab.value = tab
|
||||||
}
|
}
|
||||||
|
@ -428,6 +444,14 @@ private extension SceneCoordinator {
|
||||||
let _viewController = FavoriteViewController()
|
let _viewController = FavoriteViewController()
|
||||||
_viewController.viewModel = viewModel
|
_viewController.viewModel = viewModel
|
||||||
viewController = _viewController
|
viewController = _viewController
|
||||||
|
case .follower(let viewModel):
|
||||||
|
let _viewController = FollowerListViewController()
|
||||||
|
_viewController.viewModel = viewModel
|
||||||
|
viewController = _viewController
|
||||||
|
case .following(let viewModel):
|
||||||
|
let _viewController = FollowingListViewController()
|
||||||
|
_viewController.viewModel = viewModel
|
||||||
|
viewController = _viewController
|
||||||
case .suggestionAccount(let viewModel):
|
case .suggestionAccount(let viewModel):
|
||||||
let _viewController = SuggestionAccountViewController()
|
let _viewController = SuggestionAccountViewController()
|
||||||
_viewController.viewModel = viewModel
|
_viewController.viewModel = viewModel
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Foundation
|
||||||
|
|
||||||
enum NotificationItem {
|
enum NotificationItem {
|
||||||
case notification(objectID: NSManagedObjectID, attribute: Item.StatusAttribute)
|
case notification(objectID: NSManagedObjectID, attribute: Item.StatusAttribute)
|
||||||
|
case notificationStatus(objectID: NSManagedObjectID, attribute: Item.StatusAttribute) // display notification status without card wrapper
|
||||||
case bottomLoader
|
case bottomLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ extension NotificationItem: Equatable {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
case (.notification(let idLeft, _), .notification(let idRight, _)):
|
case (.notification(let idLeft, _), .notification(let idRight, _)):
|
||||||
return idLeft == idRight
|
return idLeft == idRight
|
||||||
|
case (.notificationStatus(let idLeft, _), .notificationStatus(let idRight, _)):
|
||||||
|
return idLeft == idRight
|
||||||
case (.bottomLoader, .bottomLoader):
|
case (.bottomLoader, .bottomLoader):
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
|
@ -32,6 +34,8 @@ extension NotificationItem: Hashable {
|
||||||
switch self {
|
switch self {
|
||||||
case .notification(let id, _):
|
case .notification(let id, _):
|
||||||
hasher.combine(id)
|
hasher.combine(id)
|
||||||
|
case .notificationStatus(let id, _):
|
||||||
|
hasher.combine(id)
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
hasher.combine(String(describing: NotificationItem.bottomLoader.self))
|
hasher.combine(String(describing: NotificationItem.bottomLoader.self))
|
||||||
}
|
}
|
||||||
|
@ -43,6 +47,8 @@ extension NotificationItem {
|
||||||
switch self {
|
switch self {
|
||||||
case .notification(let objectID, _):
|
case .notification(let objectID, _):
|
||||||
return .mastodonNotification(objectID: objectID)
|
return .mastodonNotification(objectID: objectID)
|
||||||
|
case .notificationStatus(let objectID, _):
|
||||||
|
return .mastodonNotification(objectID: objectID)
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// UserItem.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
enum UserItem: Hashable {
|
||||||
|
case follower(objectID: NSManagedObjectID)
|
||||||
|
case following(objectID: NSManagedObjectID)
|
||||||
|
case bottomLoader
|
||||||
|
case bottomHeader(text: String)
|
||||||
|
}
|
|
@ -21,9 +21,10 @@ enum NotificationSection: Equatable, Hashable {
|
||||||
extension NotificationSection {
|
extension NotificationSection {
|
||||||
static func tableViewDiffableDataSource(
|
static func tableViewDiffableDataSource(
|
||||||
for tableView: UITableView,
|
for tableView: UITableView,
|
||||||
|
dependency: NeedsDependency,
|
||||||
managedObjectContext: NSManagedObjectContext,
|
managedObjectContext: NSManagedObjectContext,
|
||||||
delegate: NotificationTableViewCellDelegate,
|
delegate: NotificationTableViewCellDelegate,
|
||||||
dependency: NeedsDependency
|
statusTableViewCellDelegate: StatusTableViewCellDelegate
|
||||||
) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> {
|
) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> {
|
||||||
UITableViewDiffableDataSource(tableView: tableView) {
|
UITableViewDiffableDataSource(tableView: tableView) {
|
||||||
[weak delegate, weak dependency]
|
[weak delegate, weak dependency]
|
||||||
|
@ -32,137 +33,45 @@ extension NotificationSection {
|
||||||
switch notificationItem {
|
switch notificationItem {
|
||||||
case .notification(let objectID, let attribute):
|
case .notification(let objectID, let attribute):
|
||||||
guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification,
|
guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification,
|
||||||
!notification.isDeleted else {
|
!notification.isDeleted
|
||||||
return UITableViewCell()
|
else { return UITableViewCell() }
|
||||||
}
|
|
||||||
|
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationStatusTableViewCell.self), for: indexPath) as! NotificationStatusTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationStatusTableViewCell.self), for: indexPath) as! NotificationStatusTableViewCell
|
||||||
cell.delegate = delegate
|
configure(
|
||||||
|
tableView: tableView,
|
||||||
// configure author
|
cell: cell,
|
||||||
cell.configure(
|
notification: notification,
|
||||||
with: AvatarConfigurableViewConfiguration(
|
dependency: dependency,
|
||||||
avatarImageURL: notification.account.avatarImageURL()
|
attribute: attribute
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
cell.delegate = delegate
|
||||||
|
return cell
|
||||||
|
|
||||||
func createActionImage() -> UIImage? {
|
case .notificationStatus(objectID: let objectID, attribute: let attribute):
|
||||||
return UIImage(
|
guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification,
|
||||||
systemName: notification.notificationType.actionImageName,
|
!notification.isDeleted,
|
||||||
withConfiguration: UIImage.SymbolConfiguration(
|
let status = notification.status,
|
||||||
pointSize: 12, weight: .semibold
|
let requestUserID = dependency.context.authenticationService.activeMastodonAuthenticationBox.value?.userID
|
||||||
)
|
else { return UITableViewCell() }
|
||||||
)?
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
|
||||||
.withTintColor(.systemBackground)
|
|
||||||
.af.imageAspectScaled(toFit: CGSize(width: 14, height: 14))
|
|
||||||
}
|
|
||||||
|
|
||||||
cell.avatarButton.badgeImageView.backgroundColor = notification.notificationType.color
|
// configure cell
|
||||||
cell.avatarButton.badgeImageView.image = createActionImage()
|
StatusSection.configureStatusTableViewCell(
|
||||||
cell.traitCollectionDidChange
|
cell: cell,
|
||||||
.receive(on: DispatchQueue.main)
|
tableView: tableView,
|
||||||
.sink { [weak cell] in
|
timelineContext: .notifications,
|
||||||
guard let cell = cell else { return }
|
dependency: dependency,
|
||||||
cell.avatarButton.badgeImageView.image = createActionImage()
|
readableLayoutFrame: tableView.readableContentGuide.layoutFrame,
|
||||||
}
|
status: status,
|
||||||
.store(in: &cell.disposeBag)
|
requestUserID: requestUserID,
|
||||||
|
statusItemAttribute: attribute
|
||||||
// configure author name, notification description, timestamp
|
)
|
||||||
let nameText = notification.account.displayNameWithFallback
|
cell.statusView.headerContainerView.isHidden = true // set header hide
|
||||||
let titleLabelText: String = {
|
cell.statusView.actionToolbarContainer.isHidden = true // set toolbar hide
|
||||||
switch notification.notificationType {
|
cell.statusView.actionToolbarPlaceholderPaddingView.isHidden = false
|
||||||
case .favourite: return L10n.Scene.Notification.userFavoritedYourPost(nameText)
|
cell.delegate = statusTableViewCellDelegate
|
||||||
case .follow: return L10n.Scene.Notification.userFollowedYou(nameText)
|
cell.isAccessibilityElement = true
|
||||||
case .followRequest: return L10n.Scene.Notification.userRequestedToFollowYou(nameText)
|
StatusSection.configureStatusAccessibilityLabel(cell: cell)
|
||||||
case .mention: return L10n.Scene.Notification.userMentionedYou(nameText)
|
|
||||||
case .poll: return L10n.Scene.Notification.userYourPollHasEnded(nameText)
|
|
||||||
case .reblog: return L10n.Scene.Notification.userRebloggedYourPost(nameText)
|
|
||||||
default: return ""
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
do {
|
|
||||||
let nameContent = MastodonContent(content: nameText, emojis: notification.account.emojiMeta)
|
|
||||||
let nameMetaContent = try MastodonMetaContent.convert(document: nameContent)
|
|
||||||
|
|
||||||
let mastodonContent = MastodonContent(content: titleLabelText, emojis: notification.account.emojiMeta)
|
|
||||||
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
|
|
||||||
|
|
||||||
cell.titleLabel.configure(content: metaContent)
|
|
||||||
|
|
||||||
if let nameRange = metaContent.string.range(of: nameMetaContent.string) {
|
|
||||||
let nsRange = NSRange(nameRange, in: metaContent.string)
|
|
||||||
cell.titleLabel.textStorage.addAttributes([
|
|
||||||
.font: UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20),
|
|
||||||
.foregroundColor: Asset.Colors.brandBlue.color,
|
|
||||||
], range: nsRange)
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
let metaContent = PlaintextMetaContent(string: titleLabelText)
|
|
||||||
cell.titleLabel.configure(content: metaContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
let createAt = notification.createAt
|
|
||||||
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
|
|
||||||
AppContext.shared.timestampUpdatePublisher
|
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak cell] _ in
|
|
||||||
guard let cell = cell else { return }
|
|
||||||
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
|
|
||||||
}
|
|
||||||
.store(in: &cell.disposeBag)
|
|
||||||
|
|
||||||
// configure follow request (if exist)
|
|
||||||
if case .followRequest = notification.notificationType {
|
|
||||||
cell.acceptButton.publisher(for: .touchUpInside)
|
|
||||||
.sink { [weak cell] _ in
|
|
||||||
guard let cell = cell else { return }
|
|
||||||
cell.delegate?.notificationTableViewCell(cell, notification: notification, acceptButtonDidPressed: cell.acceptButton)
|
|
||||||
}
|
|
||||||
.store(in: &cell.disposeBag)
|
|
||||||
cell.rejectButton.publisher(for: .touchUpInside)
|
|
||||||
.sink { [weak cell] _ in
|
|
||||||
guard let cell = cell else { return }
|
|
||||||
cell.delegate?.notificationTableViewCell(cell, notification: notification, rejectButtonDidPressed: cell.rejectButton)
|
|
||||||
}
|
|
||||||
.store(in: &cell.disposeBag)
|
|
||||||
cell.buttonStackView.isHidden = false
|
|
||||||
} else {
|
|
||||||
cell.buttonStackView.isHidden = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure status (if exist)
|
|
||||||
if let status = notification.status {
|
|
||||||
let frame = CGRect(
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: tableView.readableContentGuide.layoutFrame.width - NotificationStatusTableViewCell.statusPadding.left - NotificationStatusTableViewCell.statusPadding.right,
|
|
||||||
height: tableView.readableContentGuide.layoutFrame.height
|
|
||||||
)
|
|
||||||
StatusSection.configure(
|
|
||||||
cell: cell,
|
|
||||||
tableView: tableView,
|
|
||||||
timelineContext: .notifications,
|
|
||||||
dependency: dependency,
|
|
||||||
readableLayoutFrame: frame,
|
|
||||||
status: status,
|
|
||||||
requestUserID: notification.userID,
|
|
||||||
statusItemAttribute: attribute
|
|
||||||
)
|
|
||||||
cell.statusContainerView.isHidden = false
|
|
||||||
cell.containerStackView.alignment = .top
|
|
||||||
cell.containerStackViewBottomLayoutConstraint.constant = 0
|
|
||||||
} else {
|
|
||||||
if case .followRequest = notification.notificationType {
|
|
||||||
cell.containerStackView.alignment = .top
|
|
||||||
} else {
|
|
||||||
cell.containerStackView.alignment = .center
|
|
||||||
}
|
|
||||||
cell.statusContainerView.isHidden = true
|
|
||||||
cell.containerStackViewBottomLayoutConstraint.constant = 5 // 5pt margin when no status view
|
|
||||||
}
|
|
||||||
|
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
|
@ -174,3 +83,136 @@ extension NotificationSection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension NotificationSection {
|
||||||
|
static func configure(
|
||||||
|
tableView: UITableView,
|
||||||
|
cell: NotificationStatusTableViewCell,
|
||||||
|
notification: MastodonNotification,
|
||||||
|
dependency: NeedsDependency,
|
||||||
|
attribute: Item.StatusAttribute
|
||||||
|
) {
|
||||||
|
// configure author
|
||||||
|
cell.configure(
|
||||||
|
with: AvatarConfigurableViewConfiguration(
|
||||||
|
avatarImageURL: notification.account.avatarImageURL()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func createActionImage() -> UIImage? {
|
||||||
|
return UIImage(
|
||||||
|
systemName: notification.notificationType.actionImageName,
|
||||||
|
withConfiguration: UIImage.SymbolConfiguration(
|
||||||
|
pointSize: 12, weight: .semibold
|
||||||
|
)
|
||||||
|
)?
|
||||||
|
.withTintColor(.systemBackground)
|
||||||
|
.af.imageAspectScaled(toFit: CGSize(width: 14, height: 14))
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.avatarButton.badgeImageView.backgroundColor = notification.notificationType.color
|
||||||
|
cell.avatarButton.badgeImageView.image = createActionImage()
|
||||||
|
cell.traitCollectionDidChange
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak cell] in
|
||||||
|
guard let cell = cell else { return }
|
||||||
|
cell.avatarButton.badgeImageView.image = createActionImage()
|
||||||
|
}
|
||||||
|
.store(in: &cell.disposeBag)
|
||||||
|
|
||||||
|
// configure author name, notification description, timestamp
|
||||||
|
let nameText = notification.account.displayNameWithFallback
|
||||||
|
let titleLabelText: String = {
|
||||||
|
switch notification.notificationType {
|
||||||
|
case .favourite: return L10n.Scene.Notification.userFavoritedYourPost(nameText)
|
||||||
|
case .follow: return L10n.Scene.Notification.userFollowedYou(nameText)
|
||||||
|
case .followRequest: return L10n.Scene.Notification.userRequestedToFollowYou(nameText)
|
||||||
|
case .mention: return L10n.Scene.Notification.userMentionedYou(nameText)
|
||||||
|
case .poll: return L10n.Scene.Notification.userYourPollHasEnded(nameText)
|
||||||
|
case .reblog: return L10n.Scene.Notification.userRebloggedYourPost(nameText)
|
||||||
|
default: return ""
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
do {
|
||||||
|
let nameContent = MastodonContent(content: nameText, emojis: notification.account.emojiMeta)
|
||||||
|
let nameMetaContent = try MastodonMetaContent.convert(document: nameContent)
|
||||||
|
|
||||||
|
let mastodonContent = MastodonContent(content: titleLabelText, emojis: notification.account.emojiMeta)
|
||||||
|
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
|
||||||
|
|
||||||
|
cell.titleLabel.configure(content: metaContent)
|
||||||
|
|
||||||
|
if let nameRange = metaContent.string.range(of: nameMetaContent.string) {
|
||||||
|
let nsRange = NSRange(nameRange, in: metaContent.string)
|
||||||
|
cell.titleLabel.textStorage.addAttributes([
|
||||||
|
.font: UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20),
|
||||||
|
.foregroundColor: Asset.Colors.brandBlue.color,
|
||||||
|
], range: nsRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
let metaContent = PlaintextMetaContent(string: titleLabelText)
|
||||||
|
cell.titleLabel.configure(content: metaContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
let createAt = notification.createAt
|
||||||
|
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
|
||||||
|
AppContext.shared.timestampUpdatePublisher
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak cell] _ in
|
||||||
|
guard let cell = cell else { return }
|
||||||
|
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
|
||||||
|
}
|
||||||
|
.store(in: &cell.disposeBag)
|
||||||
|
|
||||||
|
// configure follow request (if exist)
|
||||||
|
if case .followRequest = notification.notificationType {
|
||||||
|
cell.acceptButton.publisher(for: .touchUpInside)
|
||||||
|
.sink { [weak cell] _ in
|
||||||
|
guard let cell = cell else { return }
|
||||||
|
cell.delegate?.notificationTableViewCell(cell, notification: notification, acceptButtonDidPressed: cell.acceptButton)
|
||||||
|
}
|
||||||
|
.store(in: &cell.disposeBag)
|
||||||
|
cell.rejectButton.publisher(for: .touchUpInside)
|
||||||
|
.sink { [weak cell] _ in
|
||||||
|
guard let cell = cell else { return }
|
||||||
|
cell.delegate?.notificationTableViewCell(cell, notification: notification, rejectButtonDidPressed: cell.rejectButton)
|
||||||
|
}
|
||||||
|
.store(in: &cell.disposeBag)
|
||||||
|
cell.buttonStackView.isHidden = false
|
||||||
|
} else {
|
||||||
|
cell.buttonStackView.isHidden = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure status (if exist)
|
||||||
|
if let status = notification.status {
|
||||||
|
let frame = CGRect(
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: tableView.readableContentGuide.layoutFrame.width - NotificationStatusTableViewCell.statusPadding.left - NotificationStatusTableViewCell.statusPadding.right,
|
||||||
|
height: tableView.readableContentGuide.layoutFrame.height
|
||||||
|
)
|
||||||
|
StatusSection.configure(
|
||||||
|
cell: cell,
|
||||||
|
tableView: tableView,
|
||||||
|
timelineContext: .notifications,
|
||||||
|
dependency: dependency,
|
||||||
|
readableLayoutFrame: frame,
|
||||||
|
status: status,
|
||||||
|
requestUserID: notification.userID,
|
||||||
|
statusItemAttribute: attribute
|
||||||
|
)
|
||||||
|
cell.statusContainerView.isHidden = false
|
||||||
|
cell.containerStackView.alignment = .top
|
||||||
|
cell.containerStackViewBottomLayoutConstraint.constant = 0
|
||||||
|
} else {
|
||||||
|
if case .followRequest = notification.notificationType {
|
||||||
|
cell.containerStackView.alignment = .top
|
||||||
|
} else {
|
||||||
|
cell.containerStackView.alignment = .center
|
||||||
|
}
|
||||||
|
cell.statusContainerView.isHidden = true
|
||||||
|
cell.containerStackViewBottomLayoutConstraint.constant = 5 // 5pt margin when no status view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
//
|
||||||
|
// UserSection.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
import MetaTextKit
|
||||||
|
import MastodonMeta
|
||||||
|
|
||||||
|
enum UserSection: Hashable {
|
||||||
|
case main
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UserSection {
|
||||||
|
|
||||||
|
static let logger = Logger(subsystem: "StatusSection", category: "logic")
|
||||||
|
|
||||||
|
static func tableViewDiffableDataSource(
|
||||||
|
for tableView: UITableView,
|
||||||
|
dependency: NeedsDependency,
|
||||||
|
managedObjectContext: NSManagedObjectContext
|
||||||
|
) -> UITableViewDiffableDataSource<UserSection, UserItem> {
|
||||||
|
UITableViewDiffableDataSource(tableView: tableView) { [
|
||||||
|
weak dependency
|
||||||
|
] tableView, indexPath, item -> UITableViewCell? in
|
||||||
|
guard let dependency = dependency else { return UITableViewCell() }
|
||||||
|
switch item {
|
||||||
|
case .follower(let objectID),
|
||||||
|
.following(let objectID):
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
|
||||||
|
managedObjectContext.performAndWait {
|
||||||
|
let user = managedObjectContext.object(with: objectID) as! MastodonUser
|
||||||
|
configure(cell: cell, user: user)
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
case .bottomLoader:
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
|
||||||
|
cell.startAnimating()
|
||||||
|
return cell
|
||||||
|
case .bottomHeader(let text):
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineFooterTableViewCell.self), for: indexPath) as! TimelineFooterTableViewCell
|
||||||
|
cell.messageLabel.text = text
|
||||||
|
return cell
|
||||||
|
} // end switch
|
||||||
|
} // end UITableViewDiffableDataSource
|
||||||
|
} // end static func tableViewDiffableDataSource { … }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UserSection {
|
||||||
|
|
||||||
|
static func configure(
|
||||||
|
cell: UserTableViewCell,
|
||||||
|
user: MastodonUser
|
||||||
|
) {
|
||||||
|
cell.configure(user: user)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -106,6 +106,8 @@ internal enum L10n {
|
||||||
}
|
}
|
||||||
/// Cancel
|
/// Cancel
|
||||||
internal static let cancel = L10n.tr("Localizable", "Common.Controls.Actions.Cancel")
|
internal static let cancel = L10n.tr("Localizable", "Common.Controls.Actions.Cancel")
|
||||||
|
/// Compose
|
||||||
|
internal static let compose = L10n.tr("Localizable", "Common.Controls.Actions.Compose")
|
||||||
/// Confirm
|
/// Confirm
|
||||||
internal static let confirm = L10n.tr("Localizable", "Common.Controls.Actions.Confirm")
|
internal static let confirm = L10n.tr("Localizable", "Common.Controls.Actions.Confirm")
|
||||||
/// Continue
|
/// Continue
|
||||||
|
@ -523,6 +525,14 @@ internal enum L10n {
|
||||||
/// Your Favorites
|
/// Your Favorites
|
||||||
internal static let title = L10n.tr("Localizable", "Scene.Favorite.Title")
|
internal static let title = L10n.tr("Localizable", "Scene.Favorite.Title")
|
||||||
}
|
}
|
||||||
|
internal enum Follower {
|
||||||
|
/// Followers from other servers are not displayed.
|
||||||
|
internal static let footer = L10n.tr("Localizable", "Scene.Follower.Footer")
|
||||||
|
}
|
||||||
|
internal enum Following {
|
||||||
|
/// Follows from other servers are not displayed.
|
||||||
|
internal static let footer = L10n.tr("Localizable", "Scene.Following.Footer")
|
||||||
|
}
|
||||||
internal enum HomeTimeline {
|
internal enum HomeTimeline {
|
||||||
/// Home
|
/// Home
|
||||||
internal static let title = L10n.tr("Localizable", "Scene.HomeTimeline.Title")
|
internal static let title = L10n.tr("Localizable", "Scene.HomeTimeline.Title")
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>79</string>
|
<string>83</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>LSApplicationQueriesSchemes</key>
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// StoreReviewPreference.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-3.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension UserDefaults {
|
||||||
|
|
||||||
|
@objc dynamic var processCompletedCount: Int {
|
||||||
|
get {
|
||||||
|
return integer(forKey: #function)
|
||||||
|
}
|
||||||
|
set { self[#function] = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc dynamic var lastVersionPromptedForReview: String? {
|
||||||
|
get {
|
||||||
|
return string(forKey: #function)
|
||||||
|
}
|
||||||
|
set { self[#function] = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// UserProviderFacade+UITableViewDelegate.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import CoreDataStack
|
||||||
|
import MastodonSDK
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UserTableViewCellDelegate where Self: UserProvider {
|
||||||
|
|
||||||
|
func handleTableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
guard let cell = tableView.cellForRow(at: indexPath) else { return }
|
||||||
|
let user = self.mastodonUser(for: cell)
|
||||||
|
UserProviderFacade.coordinatorToUserProfileScene(provider: self, user: user)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -440,3 +440,25 @@ extension UserProviderFacade {
|
||||||
return activityViewController
|
return activityViewController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension UserProviderFacade {
|
||||||
|
static func coordinatorToUserProfileScene(provider: UserProvider, user: Future<MastodonUser?, Never>) {
|
||||||
|
user
|
||||||
|
.sink { [weak provider] mastodonUser in
|
||||||
|
guard let provider = provider else { return }
|
||||||
|
guard let mastodonUser = mastodonUser else { return }
|
||||||
|
let profileViewModel = CachedProfileViewModel(context: provider.context, mastodonUser: mastodonUser)
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if provider.navigationController == nil {
|
||||||
|
let from = provider.presentingViewController ?? provider
|
||||||
|
provider.dismiss(animated: true) {
|
||||||
|
provider.coordinator.present(scene: .profile(viewModel: profileViewModel), from: from, transition: .show)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
provider.coordinator.present(scene: .profile(viewModel: profileViewModel), from: provider, transition: .show)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &provider.disposeBag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0.549",
|
"blue" : "0x99",
|
||||||
"green" : "0.510",
|
"green" : "0x99",
|
||||||
"red" : "0.431"
|
"red" : "0x99"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
@ -23,9 +23,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "200",
|
"blue" : "0x99",
|
||||||
"green" : "174",
|
"green" : "0x99",
|
||||||
"red" : "155"
|
"red" : "0x99"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0.549",
|
"blue" : "0x99",
|
||||||
"green" : "0.510",
|
"green" : "0x99",
|
||||||
"red" : "0.431"
|
"red" : "0x99"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
@ -23,9 +23,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "140",
|
"blue" : "0x99",
|
||||||
"green" : "130",
|
"green" : "0x99",
|
||||||
"red" : "110"
|
"red" : "0x99"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"Common.Alerts.DiscardPostContent.Message" = "Confirm to discard composed post content.";
|
"Common.Alerts.DiscardPostContent.Message" = "Confirm to discard composed post content.";
|
||||||
"Common.Alerts.DiscardPostContent.Title" = "تجاهل المسودة";
|
"Common.Alerts.DiscardPostContent.Title" = "تجاهل المسودة";
|
||||||
"Common.Alerts.EditProfileFailure.Message" = "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى.";
|
"Common.Alerts.EditProfileFailure.Message" = "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى.";
|
||||||
"Common.Alerts.EditProfileFailure.Title" = "Edit Profile Error";
|
"Common.Alerts.EditProfileFailure.Title" = "خطأ في تَحرير الملف الشخصي";
|
||||||
"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Cannot attach more than one video.";
|
"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Cannot attach more than one video.";
|
||||||
"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "Cannot attach a video to a post that already contains images.";
|
"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "Cannot attach a video to a post that already contains images.";
|
||||||
"Common.Alerts.PublishPostFailure.Message" = "Failed to publish the post.
|
"Common.Alerts.PublishPostFailure.Message" = "Failed to publish the post.
|
||||||
|
@ -28,6 +28,7 @@ Please check your internet connection.";
|
||||||
"Common.Controls.Actions.Back" = "العودة";
|
"Common.Controls.Actions.Back" = "العودة";
|
||||||
"Common.Controls.Actions.BlockDomain" = "حظر %@";
|
"Common.Controls.Actions.BlockDomain" = "حظر %@";
|
||||||
"Common.Controls.Actions.Cancel" = "إلغاء";
|
"Common.Controls.Actions.Cancel" = "إلغاء";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "تأكيد";
|
"Common.Controls.Actions.Confirm" = "تأكيد";
|
||||||
"Common.Controls.Actions.Continue" = "واصل";
|
"Common.Controls.Actions.Continue" = "واصل";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "نسخ الصورة";
|
"Common.Controls.Actions.CopyPhoto" = "نسخ الصورة";
|
||||||
|
@ -190,6 +191,8 @@ uploaded to Mastodon.";
|
||||||
اضغط على الرابط لتأكيد حسابك.";
|
اضغط على الرابط لتأكيد حسابك.";
|
||||||
"Scene.ConfirmEmail.Title" = "شيء واحد أخير.";
|
"Scene.ConfirmEmail.Title" = "شيء واحد أخير.";
|
||||||
"Scene.Favorite.Title" = "مفضلتك";
|
"Scene.Favorite.Title" = "مفضلتك";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "إظهار منشورات جديدة";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "إظهار منشورات جديدة";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "غير متصل";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "غير متصل";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "تم نشره!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "تم نشره!";
|
||||||
|
@ -275,7 +278,7 @@ uploaded to Mastodon.";
|
||||||
"Scene.Search.Searching.Segment.People" = "الأشخاص";
|
"Scene.Search.Searching.Segment.People" = "الأشخاص";
|
||||||
"Scene.Search.Searching.Segment.Posts" = "المنشورات";
|
"Scene.Search.Searching.Segment.Posts" = "المنشورات";
|
||||||
"Scene.Search.Title" = "بحث";
|
"Scene.Search.Title" = "بحث";
|
||||||
"Scene.ServerPicker.Button.Category.Academia" = "academia";
|
"Scene.ServerPicker.Button.Category.Academia" = "أكاديمي";
|
||||||
"Scene.ServerPicker.Button.Category.Activism" = "للنشطاء";
|
"Scene.ServerPicker.Button.Category.Activism" = "للنشطاء";
|
||||||
"Scene.ServerPicker.Button.Category.All" = "الكل";
|
"Scene.ServerPicker.Button.Category.All" = "الكل";
|
||||||
"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "الفئة: الكل";
|
"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "الفئة: الكل";
|
||||||
|
@ -298,8 +301,8 @@ uploaded to Mastodon.";
|
||||||
"Scene.ServerPicker.Label.Category" = "الفئة";
|
"Scene.ServerPicker.Label.Category" = "الفئة";
|
||||||
"Scene.ServerPicker.Label.Language" = "اللغة";
|
"Scene.ServerPicker.Label.Language" = "اللغة";
|
||||||
"Scene.ServerPicker.Label.Users" = "مستخدمون·ات";
|
"Scene.ServerPicker.Label.Users" = "مستخدمون·ات";
|
||||||
"Scene.ServerPicker.Title" = "Pick a server,
|
"Scene.ServerPicker.Title" = "اِختر خادِم،
|
||||||
any server.";
|
أي خادِم.";
|
||||||
"Scene.ServerRules.Button.Confirm" = "انا أوافق";
|
"Scene.ServerRules.Button.Confirm" = "انا أوافق";
|
||||||
"Scene.ServerRules.PrivacyPolicy" = "سياسة الخصوصية";
|
"Scene.ServerRules.PrivacyPolicy" = "سياسة الخصوصية";
|
||||||
"Scene.ServerRules.Prompt" = "إن اخترت المواصلة، فإنك تخضع لشروط الخدمة وسياسة الخصوصية لـ %@.";
|
"Scene.ServerRules.Prompt" = "إن اخترت المواصلة، فإنك تخضع لشروط الخدمة وسياسة الخصوصية لـ %@.";
|
||||||
|
|
|
@ -28,6 +28,7 @@ Comprova la teva connexió a Internet.";
|
||||||
"Common.Controls.Actions.Back" = "Enrere";
|
"Common.Controls.Actions.Back" = "Enrere";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Bloqueja %@";
|
"Common.Controls.Actions.BlockDomain" = "Bloqueja %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Cancel·la";
|
"Common.Controls.Actions.Cancel" = "Cancel·la";
|
||||||
|
"Common.Controls.Actions.Compose" = "Composa";
|
||||||
"Common.Controls.Actions.Confirm" = "Confirma";
|
"Common.Controls.Actions.Confirm" = "Confirma";
|
||||||
"Common.Controls.Actions.Continue" = "Continua";
|
"Common.Controls.Actions.Continue" = "Continua";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Copia la foto";
|
"Common.Controls.Actions.CopyPhoto" = "Copia la foto";
|
||||||
|
@ -190,6 +191,8 @@ carregat a Mastodon.";
|
||||||
toca l'enllaç per a confirmar el teu compte.";
|
toca l'enllaç per a confirmar el teu compte.";
|
||||||
"Scene.ConfirmEmail.Title" = "Una última cosa.";
|
"Scene.ConfirmEmail.Title" = "Una última cosa.";
|
||||||
"Scene.Favorite.Title" = "Els teus Favorits";
|
"Scene.Favorite.Title" = "Els teus Favorits";
|
||||||
|
"Scene.Follower.Footer" = "Els seguidors d'altres servidors no son mostrats.";
|
||||||
|
"Scene.Following.Footer" = "Els seguits d'altres servidors no son mostrats.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Veure noves publicacions";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Veure noves publicacions";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Fora de línia";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Fora de línia";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Publicat!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Publicat!";
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<key>a11y.plural.count.input_limit_exceeds</key>
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>El límit d’entrada supera a %#@character_count@</string>
|
<string>El límit de la entrada supera a %#@character_count@</string>
|
||||||
<key>character_count</key>
|
<key>character_count</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
<key>a11y.plural.count.input_limit_remains</key>
|
<key>a11y.plural.count.input_limit_remains</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>El límit d’entrada continua sent %#@character_count@</string>
|
<string>El límit de la entrada continua sent %#@character_count@</string>
|
||||||
<key>character_count</key>
|
<key>character_count</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>1 impuls</string>
|
<string>1 impuls</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld impuls</string>
|
<string>%ld impulsos</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>plural.count.vote</key>
|
<key>plural.count.vote</key>
|
||||||
|
@ -301,9 +301,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1a</string>
|
<string>fa 1 any</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldy anys</string>
|
<string>fa %ld anys</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.month.ago.abbr</key>
|
<key>date.month.ago.abbr</key>
|
||||||
|
@ -317,9 +317,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1M</string>
|
<string>fa 1 mes</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldM mesos</string>
|
<string>fa %ld mesos</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.day.ago.abbr</key>
|
<key>date.day.ago.abbr</key>
|
||||||
|
@ -333,9 +333,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1d</string>
|
<string>fa 1 día</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldd dies</string>
|
<string>fa %ld dies</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.hour.ago.abbr</key>
|
<key>date.hour.ago.abbr</key>
|
||||||
|
@ -351,7 +351,7 @@
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1h</string>
|
<string>fa 1h</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldh hores</string>
|
<string>fa %ld hores</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.minute.ago.abbr</key>
|
<key>date.minute.ago.abbr</key>
|
||||||
|
@ -365,9 +365,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1m</string>
|
<string>fa 1 minut</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %ldm minuts</string>
|
<string>fa %ld minuts</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.second.ago.abbr</key>
|
<key>date.second.ago.abbr</key>
|
||||||
|
@ -381,9 +381,9 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>fa 1s</string>
|
<string>fa 1 segon</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>fa %lds seg</string>
|
<string>fa %ld segons</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -28,6 +28,7 @@ Bitte überprüfe deine Internetverbindung.";
|
||||||
"Common.Controls.Actions.Back" = "Zurück";
|
"Common.Controls.Actions.Back" = "Zurück";
|
||||||
"Common.Controls.Actions.BlockDomain" = "%@ blockieren";
|
"Common.Controls.Actions.BlockDomain" = "%@ blockieren";
|
||||||
"Common.Controls.Actions.Cancel" = "Abbrechen";
|
"Common.Controls.Actions.Cancel" = "Abbrechen";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Bestätigen";
|
"Common.Controls.Actions.Confirm" = "Bestätigen";
|
||||||
"Common.Controls.Actions.Continue" = "Fortfahren";
|
"Common.Controls.Actions.Continue" = "Fortfahren";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Foto kopieren";
|
"Common.Controls.Actions.CopyPhoto" = "Foto kopieren";
|
||||||
|
@ -135,7 +136,7 @@ Dein Profil sieht für diesen Benutzer auch so aus.";
|
||||||
"Common.Controls.Timeline.Timestamp.Now" = "Gerade";
|
"Common.Controls.Timeline.Timestamp.Now" = "Gerade";
|
||||||
"Scene.AccountList.AddAccount" = "Konto hinzufügen";
|
"Scene.AccountList.AddAccount" = "Konto hinzufügen";
|
||||||
"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher";
|
"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher";
|
||||||
"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher";
|
"Scene.AccountList.TabBarHint" = "Aktuell ausgewähltes Profil: %@. Doppeltippen dann gedrückt halten, um den Kontoschalter anzuzeigen";
|
||||||
"Scene.Compose.Accessibility.AppendAttachment" = "Anhang hinzufügen";
|
"Scene.Compose.Accessibility.AppendAttachment" = "Anhang hinzufügen";
|
||||||
"Scene.Compose.Accessibility.AppendPoll" = "Umfrage hinzufügen";
|
"Scene.Compose.Accessibility.AppendPoll" = "Umfrage hinzufügen";
|
||||||
"Scene.Compose.Accessibility.CustomEmojiPicker" = "Benutzerdefinierter Emojiwähler";
|
"Scene.Compose.Accessibility.CustomEmojiPicker" = "Benutzerdefinierter Emojiwähler";
|
||||||
|
@ -190,6 +191,8 @@ kann nicht auf Mastodon hochgeladen werden.";
|
||||||
tippe darin auf den Link, um Dein Konto zu bestätigen.";
|
tippe darin auf den Link, um Dein Konto zu bestätigen.";
|
||||||
"Scene.ConfirmEmail.Title" = "Noch eine letzte Sache.";
|
"Scene.ConfirmEmail.Title" = "Noch eine letzte Sache.";
|
||||||
"Scene.Favorite.Title" = "Deine Favoriten";
|
"Scene.Favorite.Title" = "Deine Favoriten";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Neue Beiträge anzeigen";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Neue Beiträge anzeigen";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Veröffentlicht!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Veröffentlicht!";
|
||||||
|
@ -341,5 +344,5 @@ beliebigen Server.";
|
||||||
"Scene.Thread.Title" = "Beitrag von %@";
|
"Scene.Thread.Title" = "Beitrag von %@";
|
||||||
"Scene.Welcome.Slogan" = "Soziale Netzwerke wieder in deinen Händen.";
|
"Scene.Welcome.Slogan" = "Soziale Netzwerke wieder in deinen Händen.";
|
||||||
"Scene.Wizard.AccessibilityHint" = "Doppeltippen, um diesen Assistenten zu schließen";
|
"Scene.Wizard.AccessibilityHint" = "Doppeltippen, um diesen Assistenten zu schließen";
|
||||||
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button.";
|
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Wechsel zwischen mehreren Konten durch drücken der Profil-Schaltfläche.";
|
||||||
"Scene.Wizard.NewInMastodon" = "Neu in Mastodon";
|
"Scene.Wizard.NewInMastodon" = "Neu in Mastodon";
|
|
@ -28,6 +28,7 @@ Please check your internet connection.";
|
||||||
"Common.Controls.Actions.Back" = "Back";
|
"Common.Controls.Actions.Back" = "Back";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Block %@";
|
"Common.Controls.Actions.BlockDomain" = "Block %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Cancel";
|
"Common.Controls.Actions.Cancel" = "Cancel";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Confirm";
|
"Common.Controls.Actions.Confirm" = "Confirm";
|
||||||
"Common.Controls.Actions.Continue" = "Continue";
|
"Common.Controls.Actions.Continue" = "Continue";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Copy Photo";
|
"Common.Controls.Actions.CopyPhoto" = "Copy Photo";
|
||||||
|
@ -190,6 +191,8 @@ uploaded to Mastodon.";
|
||||||
tap the link to confirm your account.";
|
tap the link to confirm your account.";
|
||||||
"Scene.ConfirmEmail.Title" = "One last thing.";
|
"Scene.ConfirmEmail.Title" = "One last thing.";
|
||||||
"Scene.Favorite.Title" = "Your Favorites";
|
"Scene.Favorite.Title" = "Your Favorites";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "See new posts";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "See new posts";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Published!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Published!";
|
||||||
|
|
|
@ -28,6 +28,7 @@ Por favor, revisá tu conexión a Internet.";
|
||||||
"Common.Controls.Actions.Back" = "Volver";
|
"Common.Controls.Actions.Back" = "Volver";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Bloquear a %@";
|
"Common.Controls.Actions.BlockDomain" = "Bloquear a %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Cancelar";
|
"Common.Controls.Actions.Cancel" = "Cancelar";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Confirmar";
|
"Common.Controls.Actions.Confirm" = "Confirmar";
|
||||||
"Common.Controls.Actions.Continue" = "Continuar";
|
"Common.Controls.Actions.Continue" = "Continuar";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Copiar foto";
|
"Common.Controls.Actions.CopyPhoto" = "Copiar foto";
|
||||||
|
@ -190,6 +191,8 @@ y no se puede subir a Mastodon.";
|
||||||
pulsá en el enlace para confirmar tu cuenta.";
|
pulsá en el enlace para confirmar tu cuenta.";
|
||||||
"Scene.ConfirmEmail.Title" = "Una última cosa.";
|
"Scene.ConfirmEmail.Title" = "Una última cosa.";
|
||||||
"Scene.Favorite.Title" = "Tus favoritos";
|
"Scene.Favorite.Title" = "Tus favoritos";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevos mensajes";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevos mensajes";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Desconectado";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Desconectado";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "¡Enviado!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "¡Enviado!";
|
||||||
|
|
|
@ -28,6 +28,7 @@ Por favor, revise su conexión a internet.";
|
||||||
"Common.Controls.Actions.Back" = "Atrás";
|
"Common.Controls.Actions.Back" = "Atrás";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Bloquear %@";
|
"Common.Controls.Actions.BlockDomain" = "Bloquear %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Cancelar";
|
"Common.Controls.Actions.Cancel" = "Cancelar";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Confirmar";
|
"Common.Controls.Actions.Confirm" = "Confirmar";
|
||||||
"Common.Controls.Actions.Continue" = "Continuar";
|
"Common.Controls.Actions.Continue" = "Continuar";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Copiar foto";
|
"Common.Controls.Actions.CopyPhoto" = "Copiar foto";
|
||||||
|
@ -190,6 +191,8 @@ subirse a Mastodon.";
|
||||||
pulsa en el enlace para confirmar tu cuenta.";
|
pulsa en el enlace para confirmar tu cuenta.";
|
||||||
"Scene.ConfirmEmail.Title" = "Una última cosa.";
|
"Scene.ConfirmEmail.Title" = "Una última cosa.";
|
||||||
"Scene.Favorite.Title" = "Tus Favoritos";
|
"Scene.Favorite.Title" = "Tus Favoritos";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevas publicaciones";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevas publicaciones";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Sin Conexión";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Sin Conexión";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "¡Publicado!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "¡Publicado!";
|
||||||
|
|
|
@ -28,6 +28,7 @@ Veuillez vérifier votre accès à Internet.";
|
||||||
"Common.Controls.Actions.Back" = "Retour";
|
"Common.Controls.Actions.Back" = "Retour";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Bloquer %@";
|
"Common.Controls.Actions.BlockDomain" = "Bloquer %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Annuler";
|
"Common.Controls.Actions.Cancel" = "Annuler";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Confirmer";
|
"Common.Controls.Actions.Confirm" = "Confirmer";
|
||||||
"Common.Controls.Actions.Continue" = "Continuer";
|
"Common.Controls.Actions.Continue" = "Continuer";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Copier la photo";
|
"Common.Controls.Actions.CopyPhoto" = "Copier la photo";
|
||||||
|
@ -190,6 +191,8 @@ téléversé sur Mastodon.";
|
||||||
tapotez le lien pour confirmer votre compte.";
|
tapotez le lien pour confirmer votre compte.";
|
||||||
"Scene.ConfirmEmail.Title" = "Une dernière chose.";
|
"Scene.ConfirmEmail.Title" = "Une dernière chose.";
|
||||||
"Scene.Favorite.Title" = "Vos favoris";
|
"Scene.Favorite.Title" = "Vos favoris";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Voir les nouvelles publications";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Voir les nouvelles publications";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Hors ligne";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Hors ligne";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Publié!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Publié!";
|
||||||
|
|
|
@ -28,6 +28,7 @@ Thoir sùil air a’ cheangal agad ris an eadar-lìon.";
|
||||||
"Common.Controls.Actions.Back" = "Air ais";
|
"Common.Controls.Actions.Back" = "Air ais";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Bac %@";
|
"Common.Controls.Actions.BlockDomain" = "Bac %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Sguir dheth";
|
"Common.Controls.Actions.Cancel" = "Sguir dheth";
|
||||||
|
"Common.Controls.Actions.Compose" = "Sgrìobh";
|
||||||
"Common.Controls.Actions.Confirm" = "Dearbh";
|
"Common.Controls.Actions.Confirm" = "Dearbh";
|
||||||
"Common.Controls.Actions.Continue" = "Lean air adhart";
|
"Common.Controls.Actions.Continue" = "Lean air adhart";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Dèan lethbhreac dhen dealbh";
|
"Common.Controls.Actions.CopyPhoto" = "Dèan lethbhreac dhen dealbh";
|
||||||
|
@ -133,9 +134,9 @@ Seo an coltas a th’ air a’ phròifil agad dhaibh-san.";
|
||||||
"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "A’ luchdadh nam post a tha a dhìth…";
|
"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "A’ luchdadh nam post a tha a dhìth…";
|
||||||
"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Seall barrachd freagairtean";
|
"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Seall barrachd freagairtean";
|
||||||
"Common.Controls.Timeline.Timestamp.Now" = "An-dràsta";
|
"Common.Controls.Timeline.Timestamp.Now" = "An-dràsta";
|
||||||
"Scene.AccountList.AddAccount" = "Add Account";
|
"Scene.AccountList.AddAccount" = "Cuir cunntas ris";
|
||||||
"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher";
|
"Scene.AccountList.DismissAccountSwitcher" = "Leig seachad taghadh a’ chunntais";
|
||||||
"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher";
|
"Scene.AccountList.TabBarHint" = "A’ phròifil air a taghadh: %@. Thoir gnogag dhùbailte is cùm sìos a ghearradh leum gu cunntas eile";
|
||||||
"Scene.Compose.Accessibility.AppendAttachment" = "Cuir ceanglachan ris";
|
"Scene.Compose.Accessibility.AppendAttachment" = "Cuir ceanglachan ris";
|
||||||
"Scene.Compose.Accessibility.AppendPoll" = "Cuir cunntas-bheachd ris";
|
"Scene.Compose.Accessibility.AppendPoll" = "Cuir cunntas-bheachd ris";
|
||||||
"Scene.Compose.Accessibility.CustomEmojiPicker" = "Roghnaichear nan Emoji gnàthaichte";
|
"Scene.Compose.Accessibility.CustomEmojiPicker" = "Roghnaichear nan Emoji gnàthaichte";
|
||||||
|
@ -190,6 +191,8 @@ a luchdadh suas gu Mastodon.";
|
||||||
thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad.";
|
thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad.";
|
||||||
"Scene.ConfirmEmail.Title" = "Aon rud eile.";
|
"Scene.ConfirmEmail.Title" = "Aon rud eile.";
|
||||||
"Scene.Favorite.Title" = "Na h-annsachdan agad";
|
"Scene.Favorite.Title" = "Na h-annsachdan agad";
|
||||||
|
"Scene.Follower.Footer" = "Cha dèid luchd-leantainn o fhrithealaichean eile a shealltainn.";
|
||||||
|
"Scene.Following.Footer" = "Cha dèid cò air a leanas tu air frithealaichean eile a shealltainn.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Seall na postaichean ùra";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Seall na postaichean ùra";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Far loidhne";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Far loidhne";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Chaidh fhoillseachadh!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Chaidh fhoillseachadh!";
|
||||||
|
@ -340,6 +343,6 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad.";
|
||||||
"Scene.Thread.Title" = "Post le %@";
|
"Scene.Thread.Title" = "Post le %@";
|
||||||
"Scene.Welcome.Slogan" = "A’ cur nan lìonraidhean sòisealta
|
"Scene.Welcome.Slogan" = "A’ cur nan lìonraidhean sòisealta
|
||||||
’nad làmhan fhèin.";
|
’nad làmhan fhèin.";
|
||||||
"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard";
|
"Scene.Wizard.AccessibilityHint" = "Thoir gnogag dhùbailte a’ leigeil seachad an draoidh seo";
|
||||||
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button.";
|
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Geàrr leum eadar iomadh cunntas le cumail sìos putan na pròifil.";
|
||||||
"Scene.Wizard.NewInMastodon" = "New in Mastodon";
|
"Scene.Wizard.NewInMastodon" = "Na tha ùr ann am Mastodon";
|
|
@ -13,13 +13,13 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>1 unread notification</string>
|
<string>%ld bhrath nach deach a leughadh</string>
|
||||||
<key>two</key>
|
<key>two</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld bhrath nach deach a leughadh</string>
|
||||||
<key>few</key>
|
<key>few</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld brathan nach deach a leughadh</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld brath nach deach a leughadh</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>a11y.plural.count.input_limit_exceeds</key>
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"Common.Controls.Actions.Back" = "戻る";
|
"Common.Controls.Actions.Back" = "戻る";
|
||||||
"Common.Controls.Actions.BlockDomain" = "%@をブロック";
|
"Common.Controls.Actions.BlockDomain" = "%@をブロック";
|
||||||
"Common.Controls.Actions.Cancel" = "キャンセル";
|
"Common.Controls.Actions.Cancel" = "キャンセル";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "確認";
|
"Common.Controls.Actions.Confirm" = "確認";
|
||||||
"Common.Controls.Actions.Continue" = "続ける";
|
"Common.Controls.Actions.Continue" = "続ける";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "写真をコピー";
|
"Common.Controls.Actions.CopyPhoto" = "写真をコピー";
|
||||||
|
@ -129,7 +130,7 @@
|
||||||
"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "読込中...";
|
"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "読込中...";
|
||||||
"Common.Controls.Timeline.Loader.ShowMoreReplies" = "リプライをもっとみる";
|
"Common.Controls.Timeline.Loader.ShowMoreReplies" = "リプライをもっとみる";
|
||||||
"Common.Controls.Timeline.Timestamp.Now" = "今";
|
"Common.Controls.Timeline.Timestamp.Now" = "今";
|
||||||
"Scene.AccountList.AddAccount" = "Add Account";
|
"Scene.AccountList.AddAccount" = "アカウントを追加";
|
||||||
"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher";
|
"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher";
|
||||||
"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher";
|
"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher";
|
||||||
"Scene.Compose.Accessibility.AppendAttachment" = "アタッチメントの追加";
|
"Scene.Compose.Accessibility.AppendAttachment" = "アタッチメントの追加";
|
||||||
|
@ -184,6 +185,8 @@
|
||||||
"Scene.ConfirmEmail.Subtitle" = "先程 %@ にメールを送信しました。リンクをタップしてアカウントを確認してください。";
|
"Scene.ConfirmEmail.Subtitle" = "先程 %@ にメールを送信しました。リンクをタップしてアカウントを確認してください。";
|
||||||
"Scene.ConfirmEmail.Title" = "さいごにもうひとつ。";
|
"Scene.ConfirmEmail.Title" = "さいごにもうひとつ。";
|
||||||
"Scene.Favorite.Title" = "お気に入り";
|
"Scene.Favorite.Title" = "お気に入り";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "新しい投稿を見る";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "新しい投稿を見る";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "オフライン";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "オフライン";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "投稿しました!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "投稿しました!";
|
||||||
|
@ -332,8 +335,7 @@
|
||||||
"Scene.SuggestionAccount.Title" = "フォローする人を探す";
|
"Scene.SuggestionAccount.Title" = "フォローする人を探す";
|
||||||
"Scene.Thread.BackTitle" = "投稿";
|
"Scene.Thread.BackTitle" = "投稿";
|
||||||
"Scene.Thread.Title" = "%@の投稿";
|
"Scene.Thread.Title" = "%@の投稿";
|
||||||
"Scene.Welcome.Slogan" = "Social networking
|
"Scene.Welcome.Slogan" = "ソーシャルネットワーキングを、あなたの手の中に.";
|
||||||
back in your hands.";
|
|
||||||
"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard";
|
"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard";
|
||||||
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button.";
|
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "プロフィールボタンを押して複数のアカウントを切り替えます。";
|
||||||
"Scene.Wizard.NewInMastodon" = "New in Mastodon";
|
"Scene.Wizard.NewInMastodon" = "Mastodon の新機能";
|
|
@ -13,7 +13,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld unread notification</string>
|
<string>%ld 件の未読通知</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>a11y.plural.count.input_limit_exceeds</key>
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld characters</string>
|
<string>%ld 文字</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>a11y.plural.count.input_limit_remains</key>
|
<key>a11y.plural.count.input_limit_remains</key>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld characters</string>
|
<string>%ld 文字</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>plural.count.metric_formatted.post</key>
|
<key>plural.count.metric_formatted.post</key>
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld votes</string>
|
<string>%ld票</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>plural.count.voter</key>
|
<key>plural.count.voter</key>
|
||||||
|
@ -195,7 +195,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ld months left</string>
|
<string>%ldか月前</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.day.left</key>
|
<key>date.day.left</key>
|
||||||
|
@ -279,7 +279,7 @@
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>ld</string>
|
<string>ld</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%ldM ago</string>
|
<string>%ld分前</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>date.day.ago.abbr</key>
|
<key>date.day.ago.abbr</key>
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
"NSCameraUsageDescription" = "Bo kişandina wêneyê ji bo rewşa şandiyan tê bikaranîn";
|
||||||
|
"NSPhotoLibraryAddUsageDescription" = "Ji bo tomarkirina wêneyê di pirtûkxaneya wêneyan de tê bikaranîn";
|
||||||
|
"NewPostShortcutItemTitle" = "Şandiya nû";
|
||||||
|
"SearchShortcutItemTitle" = "Bigere";
|
|
@ -0,0 +1,349 @@
|
||||||
|
"Common.Alerts.BlockDomain.BlockEntireDomain" = "Navperê asteng bike";
|
||||||
|
"Common.Alerts.BlockDomain.Title" = "Tu ji xwe bawerî, bi rastî tu dixwazî hemû %@ asteng bikî? Di gelek rewşan de asteng kirin an jî bêdeng kirin têrê dike û tê tercîh kirin. Tu nikarî naveroka vê navperê di demnameyê an jî agahdariyên xwe de bibînî. Şopînerên te yê di vê navperê were jêbirin.";
|
||||||
|
"Common.Alerts.CleanCache.Message" = "Pêşbîra %@ biserketî hate paqijkirin.";
|
||||||
|
"Common.Alerts.CleanCache.Title" = "Pêşbîrê paqij bike";
|
||||||
|
"Common.Alerts.Common.PleaseTryAgain" = "Ji kerema xwe dîsa biceribîne.";
|
||||||
|
"Common.Alerts.Common.PleaseTryAgainLater" = "Ji kerema xwe paşê dîsa biceribîne.";
|
||||||
|
"Common.Alerts.DeletePost.Delete" = "Jê bibe";
|
||||||
|
"Common.Alerts.DeletePost.Title" = "Ma tu dixwazî vê şandiyê jê bibî?";
|
||||||
|
"Common.Alerts.DiscardPostContent.Message" = "Piştrast bikin ku naveroka posteyê ya hatîye nivîsandin jê bibin.";
|
||||||
|
"Common.Alerts.DiscardPostContent.Title" = "Reşnivîs jêbibe";
|
||||||
|
"Common.Alerts.EditProfileFailure.Message" = "Nikare profîlê serrast bike. Jkx dîsa biceribîne.";
|
||||||
|
"Common.Alerts.EditProfileFailure.Title" = "Çewtiya profîlê biguherîne";
|
||||||
|
"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Nikare ji bêtirî yek vîdyoyekê tevlî şandiyê bike.";
|
||||||
|
"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "Nikare vîdyoyekê tevlî şandiyê ku berê wêne tê de heye bike.";
|
||||||
|
"Common.Alerts.PublishPostFailure.Message" = "Weşandina şandiyê têkçû.
|
||||||
|
Jkx girêdana înternetê xwe kontrol bike.";
|
||||||
|
"Common.Alerts.PublishPostFailure.Title" = "Weşandin têkçû";
|
||||||
|
"Common.Alerts.SavePhotoFailure.Message" = "Ji kerema xwe destûra gihîştina pirtûkxaneya wêneyê çalak bikin da ku wêneyê hilînin.";
|
||||||
|
"Common.Alerts.SavePhotoFailure.Title" = "Tomarkirina wêneyê têkçû";
|
||||||
|
"Common.Alerts.ServerError.Title" = "Çewtiya rajekar";
|
||||||
|
"Common.Alerts.SignOut.Confirm" = "Derkeve";
|
||||||
|
"Common.Alerts.SignOut.Message" = "Ma tu dixwazî ku derkevî?";
|
||||||
|
"Common.Alerts.SignOut.Title" = "Derkeve";
|
||||||
|
"Common.Alerts.SignUpFailure.Title" = "Tomarkirin têkçû";
|
||||||
|
"Common.Alerts.VoteFailure.PollEnded" = "Rapirsîya qediya";
|
||||||
|
"Common.Alerts.VoteFailure.Title" = "Dengdayîn têkçû";
|
||||||
|
"Common.Controls.Actions.Add" = "Tevlî bike";
|
||||||
|
"Common.Controls.Actions.Back" = "Vegere";
|
||||||
|
"Common.Controls.Actions.BlockDomain" = "%@ asteng bike";
|
||||||
|
"Common.Controls.Actions.Cancel" = "Dev jê berde";
|
||||||
|
"Common.Controls.Actions.Compose" = "Binivîsîne";
|
||||||
|
"Common.Controls.Actions.Confirm" = "Bipejirîne";
|
||||||
|
"Common.Controls.Actions.Continue" = "Bidomîne";
|
||||||
|
"Common.Controls.Actions.CopyPhoto" = "Wêne kopî bikin";
|
||||||
|
"Common.Controls.Actions.Delete" = "Jê bibe";
|
||||||
|
"Common.Controls.Actions.Discard" = "Biavêje";
|
||||||
|
"Common.Controls.Actions.Done" = "Qediya";
|
||||||
|
"Common.Controls.Actions.Edit" = "Serrast bike";
|
||||||
|
"Common.Controls.Actions.FindPeople" = "Kesên ku bişopînin bibînin";
|
||||||
|
"Common.Controls.Actions.ManuallySearch" = "Ji devlê i destan lêgerînê bike";
|
||||||
|
"Common.Controls.Actions.Next" = "Pêş";
|
||||||
|
"Common.Controls.Actions.Ok" = "BAŞ E";
|
||||||
|
"Common.Controls.Actions.Open" = "Veke";
|
||||||
|
"Common.Controls.Actions.OpenInSafari" = "Di Safariyê de veke";
|
||||||
|
"Common.Controls.Actions.Preview" = "Pêşdîtin";
|
||||||
|
"Common.Controls.Actions.Previous" = "Paş";
|
||||||
|
"Common.Controls.Actions.Remove" = "Rake";
|
||||||
|
"Common.Controls.Actions.Reply" = "Bersivê bide";
|
||||||
|
"Common.Controls.Actions.ReportUser" = "%@ ragihîne";
|
||||||
|
"Common.Controls.Actions.Save" = "Tomar bike";
|
||||||
|
"Common.Controls.Actions.SavePhoto" = "Wêneyê hilîne";
|
||||||
|
"Common.Controls.Actions.SeeMore" = "Bêtir bibîne";
|
||||||
|
"Common.Controls.Actions.Settings" = "Sazkarî";
|
||||||
|
"Common.Controls.Actions.Share" = "Parve bike";
|
||||||
|
"Common.Controls.Actions.SharePost" = "Şandiyê parve bike";
|
||||||
|
"Common.Controls.Actions.ShareUser" = "%@ parve bike";
|
||||||
|
"Common.Controls.Actions.SignIn" = "Têkeve";
|
||||||
|
"Common.Controls.Actions.SignUp" = "Tomar bibe";
|
||||||
|
"Common.Controls.Actions.Skip" = "Derbas bike";
|
||||||
|
"Common.Controls.Actions.TakePhoto" = "Wêne bikişîne";
|
||||||
|
"Common.Controls.Actions.TryAgain" = "Dîsa biceribîne";
|
||||||
|
"Common.Controls.Actions.UnblockDomain" = "%@ asteng neke";
|
||||||
|
"Common.Controls.Friendship.Block" = "Asteng bike";
|
||||||
|
"Common.Controls.Friendship.BlockDomain" = "%@ asteng bike";
|
||||||
|
"Common.Controls.Friendship.BlockUser" = "%@ asteng bike";
|
||||||
|
"Common.Controls.Friendship.Blocked" = "Astengkirî";
|
||||||
|
"Common.Controls.Friendship.EditInfo" = "Zanyariyan serrast bike";
|
||||||
|
"Common.Controls.Friendship.Follow" = "Bişopîne";
|
||||||
|
"Common.Controls.Friendship.Following" = "Dişopîne";
|
||||||
|
"Common.Controls.Friendship.Mute" = "Bêdeng bike";
|
||||||
|
"Common.Controls.Friendship.MuteUser" = "%@ bêdeng bike";
|
||||||
|
"Common.Controls.Friendship.Muted" = "Bêdengkirî";
|
||||||
|
"Common.Controls.Friendship.Pending" = "Tê nirxandin";
|
||||||
|
"Common.Controls.Friendship.Request" = "Daxwazên şopandinê";
|
||||||
|
"Common.Controls.Friendship.Unblock" = "Astengiyê rake";
|
||||||
|
"Common.Controls.Friendship.UnblockUser" = "%@ asteng neke";
|
||||||
|
"Common.Controls.Friendship.Unmute" = "Bêdeng neke";
|
||||||
|
"Common.Controls.Friendship.UnmuteUser" = "%@ bêdeng neke";
|
||||||
|
"Common.Controls.Keyboard.Common.ComposeNewPost" = "Şandiyeke nû binivsîne";
|
||||||
|
"Common.Controls.Keyboard.Common.OpenSettings" = "Sazkariyan Veke";
|
||||||
|
"Common.Controls.Keyboard.Common.ShowFavorites" = "Bijarteyan nîşan bide";
|
||||||
|
"Common.Controls.Keyboard.Common.SwitchToTab" = "Biguherîne bo %@";
|
||||||
|
"Common.Controls.Keyboard.SegmentedControl.NextSection" = "Beşa paşê";
|
||||||
|
"Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "Beşa berê";
|
||||||
|
"Common.Controls.Keyboard.Timeline.NextStatus" = "Şandiya pêş";
|
||||||
|
"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "Profîla nivîskaran veke";
|
||||||
|
"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Profîla nivîskaran veke";
|
||||||
|
"Common.Controls.Keyboard.Timeline.OpenStatus" = "Şandiyê veke";
|
||||||
|
"Common.Controls.Keyboard.Timeline.PreviewImage" = "Wêneya pêşdîtinê";
|
||||||
|
"Common.Controls.Keyboard.Timeline.PreviousStatus" = "Şandeya paş";
|
||||||
|
"Common.Controls.Keyboard.Timeline.ReplyStatus" = "Bersivê bide şandiyê";
|
||||||
|
"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Hişyariya naverokê veke/bigire";
|
||||||
|
"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Di postê da Bijartin veke/bigire";
|
||||||
|
"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Ji vû nivîsandin di şandiyê de biguherîne";
|
||||||
|
"Common.Controls.Status.Actions.Favorite" = "Bijartî";
|
||||||
|
"Common.Controls.Status.Actions.Menu" = "Menû";
|
||||||
|
"Common.Controls.Status.Actions.Reblog" = "Ji nû ve blog";
|
||||||
|
"Common.Controls.Status.Actions.Reply" = "Bersivê bide";
|
||||||
|
"Common.Controls.Status.Actions.Unfavorite" = "Nebijare";
|
||||||
|
"Common.Controls.Status.Actions.Unreblog" = "Ji nû ve blogkirin betal bikin";
|
||||||
|
"Common.Controls.Status.ContentWarning" = "Hişyariya naverokê";
|
||||||
|
"Common.Controls.Status.MediaContentWarning" = "Ji bo aşkerakirinê derekî bitikîne";
|
||||||
|
"Common.Controls.Status.Poll.Closed" = "Girtî";
|
||||||
|
"Common.Controls.Status.Poll.Vote" = "Deng";
|
||||||
|
"Common.Controls.Status.ShowPost" = "Şandiyê nîşan bide";
|
||||||
|
"Common.Controls.Status.ShowUserProfile" = "Profîla bikarhêner nîşan bide";
|
||||||
|
"Common.Controls.Status.Tag.Email" = "E-name";
|
||||||
|
"Common.Controls.Status.Tag.Emoji" = "E-name";
|
||||||
|
"Common.Controls.Status.Tag.Hashtag" = "Etîket";
|
||||||
|
"Common.Controls.Status.Tag.Link" = "Girêdan";
|
||||||
|
"Common.Controls.Status.Tag.Mention" = "Behs";
|
||||||
|
"Common.Controls.Status.Tag.Url" = "URL";
|
||||||
|
"Common.Controls.Status.UserReblogged" = "%@ ji nû ve hat blogkirin";
|
||||||
|
"Common.Controls.Status.UserRepliedTo" = "Bersiv da %@";
|
||||||
|
"Common.Controls.Tabs.Home" = "Serrûpel";
|
||||||
|
"Common.Controls.Tabs.Notification" = "Agahdarî";
|
||||||
|
"Common.Controls.Tabs.Profile" = "Profîl";
|
||||||
|
"Common.Controls.Tabs.Search" = "Bigere";
|
||||||
|
"Common.Controls.Timeline.Filtered" = "Parzûnkirî";
|
||||||
|
"Common.Controls.Timeline.Header.BlockedWarning" = "Tu nikarî profîla vî bikarhênerî bibînî
|
||||||
|
heta ku astengîya te rakin.";
|
||||||
|
"Common.Controls.Timeline.Header.BlockingWarning" = "Tu nikarî profîla vî bikarhênerî bibînî
|
||||||
|
Heta ku tu wan asteng bikî.
|
||||||
|
Profîla te ji wan ra wiha xuya dike.";
|
||||||
|
"Common.Controls.Timeline.Header.NoStatusFound" = "Şandî nehate dîtin";
|
||||||
|
"Common.Controls.Timeline.Header.SuspendedWarning" = "Ev bikarhêner hat sekinandin.";
|
||||||
|
"Common.Controls.Timeline.Header.UserBlockedWarning" = "Tu nikarî profîla %@ bibînî
|
||||||
|
Heta ku astengîya te rakin.";
|
||||||
|
"Common.Controls.Timeline.Header.UserBlockingWarning" = "Tu nikarî profîla %@ bibînî
|
||||||
|
Heta ku tu wan asteng bikî.
|
||||||
|
Profîla te ji wan ra wiha xuya dike.";
|
||||||
|
"Common.Controls.Timeline.Header.UserSuspendedWarning" = "Hesaba %@ hat sekinandin.";
|
||||||
|
"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Barkirina posteyên kêm";
|
||||||
|
"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Barkirina posteyên kêm...";
|
||||||
|
"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Bêtir bersivan nîşan bide";
|
||||||
|
"Common.Controls.Timeline.Timestamp.Now" = "Niha";
|
||||||
|
"Scene.AccountList.AddAccount" = "Ajimêr tevlî bike";
|
||||||
|
"Scene.AccountList.DismissAccountSwitcher" = "Guherkera ajimêrê paş guh bike";
|
||||||
|
"Scene.AccountList.TabBarHint" = "Profîla hilbijartî ya niha: %@. Du caran bitikîne û paşê dest bide ser da ku guhêrbara ajimêr were nîşandan";
|
||||||
|
"Scene.Compose.Accessibility.AppendAttachment" = "Pêvek tevlî bike";
|
||||||
|
"Scene.Compose.Accessibility.AppendPoll" = "Rapirsî tevlî bike";
|
||||||
|
"Scene.Compose.Accessibility.CustomEmojiPicker" = "Hilbijêrê emojî yên kesanekirî";
|
||||||
|
"Scene.Compose.Accessibility.DisableContentWarning" = "Hişyariya naverokê neçalak bike";
|
||||||
|
"Scene.Compose.Accessibility.EnableContentWarning" = "Hişyariya naverokê neçalak bike";
|
||||||
|
"Scene.Compose.Accessibility.PostVisibilityMenu" = "Menuya Xuyabûna Şandiyê";
|
||||||
|
"Scene.Compose.Accessibility.RemovePoll" = "Rapirsî rake";
|
||||||
|
"Scene.Compose.Attachment.AttachmentBroken" = "Ev %@ naxebite û nayê barkirin
|
||||||
|
li ser Mastodon.";
|
||||||
|
"Scene.Compose.Attachment.DescriptionPhoto" = "Wêneyê ji bo kêmbînên dîtbar bide nasîn...";
|
||||||
|
"Scene.Compose.Attachment.DescriptionVideo" = "Vîdyoyê ji bo kêmbînên dîtbar bide nasîn...";
|
||||||
|
"Scene.Compose.Attachment.Photo" = "wêne";
|
||||||
|
"Scene.Compose.Attachment.Video" = "vîdyo";
|
||||||
|
"Scene.Compose.AutoComplete.SpaceToAdd" = "Bicîhkirinê tevlî bike";
|
||||||
|
"Scene.Compose.ComposeAction" = "Biweşîne";
|
||||||
|
"Scene.Compose.ContentInputPlaceholder" = "Tiştê ku di hişê te de ye binivîsin an jî pêve bike";
|
||||||
|
"Scene.Compose.ContentWarning.Placeholder" = "Li vir hişyariyek hûrgilî binivîsine...";
|
||||||
|
"Scene.Compose.Keyboard.AppendAttachmentEntry" = "Pêvek lê zêde bike - %@";
|
||||||
|
"Scene.Compose.Keyboard.DiscardPost" = "Şandî bihelîne";
|
||||||
|
"Scene.Compose.Keyboard.PublishPost" = "Şandiye bide weşan";
|
||||||
|
"Scene.Compose.Keyboard.SelectVisibilityEntry" = "Xuyanîbûn hilbijêre - %@";
|
||||||
|
"Scene.Compose.Keyboard.ToggleContentWarning" = "Hişyariya naverokê veke/bigire";
|
||||||
|
"Scene.Compose.Keyboard.TogglePoll" = "Anketê veke/bigire";
|
||||||
|
"Scene.Compose.MediaSelection.Browse" = "Bigere";
|
||||||
|
"Scene.Compose.MediaSelection.Camera" = "Wêne bikişîne";
|
||||||
|
"Scene.Compose.MediaSelection.PhotoLibrary" = "Wênegeh";
|
||||||
|
"Scene.Compose.Poll.DurationTime" = "Dirêjî: %@";
|
||||||
|
"Scene.Compose.Poll.OneDay" = "1 Roj";
|
||||||
|
"Scene.Compose.Poll.OneHour" = "1 Demjimêr";
|
||||||
|
"Scene.Compose.Poll.OptionNumber" = "Vebijêrk %ld";
|
||||||
|
"Scene.Compose.Poll.SevenDays" = "7 Roj";
|
||||||
|
"Scene.Compose.Poll.SixHours" = "6 Demjimêr";
|
||||||
|
"Scene.Compose.Poll.ThirtyMinutes" = "30 xulek";
|
||||||
|
"Scene.Compose.Poll.ThreeDays" = "3 Roj";
|
||||||
|
"Scene.Compose.ReplyingToUser" = "bersiv bide %@";
|
||||||
|
"Scene.Compose.Title.NewPost" = "Şandiya nû";
|
||||||
|
"Scene.Compose.Title.NewReply" = "Bersiva nû";
|
||||||
|
"Scene.Compose.Visibility.Direct" = "Tenê mirovên ku min qalkirî";
|
||||||
|
"Scene.Compose.Visibility.Private" = "Tenê şopîneran";
|
||||||
|
"Scene.Compose.Visibility.Public" = "Gelemperî";
|
||||||
|
"Scene.Compose.Visibility.Unlisted" = "Nerêzokkirî";
|
||||||
|
"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Min hîç e-nameyeke nesitand";
|
||||||
|
"Scene.ConfirmEmail.Button.OpenEmailApp" = "Sepana e-nameyê veke";
|
||||||
|
"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Kontrol bike ka navnîşana e-nameya te rast e û her wiha peldanka xwe ya spam.";
|
||||||
|
"Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "E-namyê yê dîsa bişîne";
|
||||||
|
"Scene.ConfirmEmail.DontReceiveEmail.Title" = "E-nameyê xwe kontrol bike";
|
||||||
|
"Scene.ConfirmEmail.OpenEmailApp.Description" = "Me tenê ji te re e-nameyek şand. Heke nehatiye peldanka xwe ya spamê kontrol bike.";
|
||||||
|
"Scene.ConfirmEmail.OpenEmailApp.Mail" = "E-name";
|
||||||
|
"Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Rajegirê e-nameyê veke";
|
||||||
|
"Scene.ConfirmEmail.OpenEmailApp.Title" = "Nameyên xwe yên wergirtî kontrol bike.";
|
||||||
|
"Scene.ConfirmEmail.Subtitle" = "Me tenê e-nameyek ji %@ re şand,
|
||||||
|
girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin.";
|
||||||
|
"Scene.ConfirmEmail.Title" = "Tiştekî dawî.";
|
||||||
|
"Scene.Favorite.Title" = "Bijareyên te";
|
||||||
|
"Scene.Follower.Footer" = "Şopîner ji rajekerên din nayê dîtin.";
|
||||||
|
"Scene.Following.Footer" = "Şopandin ji rajekerên din nayê dîtin.";
|
||||||
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Şandiyên nû bibîne";
|
||||||
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Derhêl";
|
||||||
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Hate weşandin!";
|
||||||
|
"Scene.HomeTimeline.NavigationBarState.Publishing" = "Şandî tê weşandin...";
|
||||||
|
"Scene.HomeTimeline.Title" = "Serrûpel";
|
||||||
|
"Scene.Notification.Keyobard.ShowEverything" = "Her tiştî nîşan bide";
|
||||||
|
"Scene.Notification.Keyobard.ShowMentions" = "Behskirîya nîşan bike";
|
||||||
|
"Scene.Notification.Title.Everything" = "Her tişt";
|
||||||
|
"Scene.Notification.Title.Mentions" = "Behs";
|
||||||
|
"Scene.Notification.UserFavorited Your Post" = "%@ posta we bijarte";
|
||||||
|
"Scene.Notification.UserFollowedYou" = "%@ te şopand";
|
||||||
|
"Scene.Notification.UserMentionedYou" = "%@ behsa te kir";
|
||||||
|
"Scene.Notification.UserRebloggedYourPost" = "%@ posta we ji nû ve tomar kir";
|
||||||
|
"Scene.Notification.UserRequestedToFollowYou" = "%@ daxwaza şopandina te kir";
|
||||||
|
"Scene.Notification.UserYourPollHasEnded" = "%@ Anketa te qediya";
|
||||||
|
"Scene.Preview.Keyboard.ClosePreview" = "Pêşdîtin bigire";
|
||||||
|
"Scene.Preview.Keyboard.ShowNext" = "A pêş nîşan bide";
|
||||||
|
"Scene.Preview.Keyboard.ShowPrevious" = "A paş nîşan bide";
|
||||||
|
"Scene.Profile.Dashboard.Followers" = "şopîneran";
|
||||||
|
"Scene.Profile.Dashboard.Following" = "dişopîne";
|
||||||
|
"Scene.Profile.Dashboard.Posts" = "şandîyan";
|
||||||
|
"Scene.Profile.Fields.AddRow" = "Rêzê lê zêde bike";
|
||||||
|
"Scene.Profile.Fields.Placeholder.Content" = "Naverok";
|
||||||
|
"Scene.Profile.Fields.Placeholder.Label" = "Nîşan";
|
||||||
|
"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Ji bo rakirina blokê bipejirin %@";
|
||||||
|
"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Hesabê ji bloke rake";
|
||||||
|
"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Ji bo vekirina bê dengkirinê bipejirin %@";
|
||||||
|
"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Hesabê ji bê deng rake";
|
||||||
|
"Scene.Profile.SegmentedControl.Media" = "Medya";
|
||||||
|
"Scene.Profile.SegmentedControl.Posts" = "Şandîyan";
|
||||||
|
"Scene.Profile.SegmentedControl.Replies" = "Bersivan";
|
||||||
|
"Scene.Register.Error.Item.Agreement" = "Lihevhatin";
|
||||||
|
"Scene.Register.Error.Item.Email" = "E-name";
|
||||||
|
"Scene.Register.Error.Item.Locale" = "Herêm";
|
||||||
|
"Scene.Register.Error.Item.Password" = "Şîfre";
|
||||||
|
"Scene.Register.Error.Item.Reason" = "Sedem";
|
||||||
|
"Scene.Register.Error.Item.Username" = "Navê bikarhêner";
|
||||||
|
"Scene.Register.Error.Reason.Accepted" = "%@ divê were qebûlkirin";
|
||||||
|
"Scene.Register.Error.Reason.Blank" = "%@ pêwist e";
|
||||||
|
"Scene.Register.Error.Reason.Blocked" = "%@ peydekerê e-nameya bêdestûr dihewîne";
|
||||||
|
"Scene.Register.Error.Reason.Inclusion" = "%@ nirxeke ku tê destekirin nîn e";
|
||||||
|
"Scene.Register.Error.Reason.Invalid" = "%@ ne derbasdar e";
|
||||||
|
"Scene.Register.Error.Reason.Reserved" = "%@ peyveke mifteya veqetandî ye";
|
||||||
|
"Scene.Register.Error.Reason.Taken" = "%@ jixwe tê bikaranîn";
|
||||||
|
"Scene.Register.Error.Reason.TooLong" = "%@ gelekî dirêj e";
|
||||||
|
"Scene.Register.Error.Reason.TooShort" = "%@ pir kurt e";
|
||||||
|
"Scene.Register.Error.Reason.Unreachable" = "%@ xuya nake";
|
||||||
|
"Scene.Register.Error.Special.EmailInvalid" = "Ev ne navnîşana e-nameyek derbasdar e";
|
||||||
|
"Scene.Register.Error.Special.PasswordTooShort" = "Şîfre pir kurt e (divê herî kêm 8 tîpan be)";
|
||||||
|
"Scene.Register.Error.Special.UsernameInvalid" = "Navê bikarhêner divê tenê tîpên alfanumerîk û binxet hebe";
|
||||||
|
"Scene.Register.Error.Special.UsernameTooLong" = "Navê bikarhêner pir dirêj e (ji 30 tîpan dirêjtir nabe)";
|
||||||
|
"Scene.Register.Input.Avatar.Delete" = "Jê bibe";
|
||||||
|
"Scene.Register.Input.DisplayName.Placeholder" = "navê nîşanê";
|
||||||
|
"Scene.Register.Input.Email.Placeholder" = "e-name";
|
||||||
|
"Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Tu çima dixwazî beşdar bibî?";
|
||||||
|
"Scene.Register.Input.Password.Hint" = "Şîfreya we herî kêm heşt tîpan hewce dike";
|
||||||
|
"Scene.Register.Input.Password.Placeholder" = "şîfre";
|
||||||
|
"Scene.Register.Input.Username.DuplicatePrompt" = "Navê vê bikarhêner tê girtin.";
|
||||||
|
"Scene.Register.Input.Username.Placeholder" = "navê bikarhêner";
|
||||||
|
"Scene.Register.Title" = "Ji me re hinekî qala xwe bike.";
|
||||||
|
"Scene.Report.Content1" = "Şandiyên din hene ku tu dixwazî tevlî ragihandinê bikî?";
|
||||||
|
"Scene.Report.Content2" = "Derbarê vê ragihandinê de tiştek heye ku divê çavdêr bizanin?";
|
||||||
|
"Scene.Report.Send" = "Ragihandinê bişîne";
|
||||||
|
"Scene.Report.SkipToSend" = "Bêyî şirove bişîne";
|
||||||
|
"Scene.Report.Step1" = "Gav 1 ji 2";
|
||||||
|
"Scene.Report.Step2" = "Gav 2 ji 2";
|
||||||
|
"Scene.Report.TextPlaceholder" = "Şiroveyên daxwazkirê binivîsine an jî pê ve bike";
|
||||||
|
"Scene.Report.Title" = "%@ ragihîne";
|
||||||
|
"Scene.Search.Recommend.Accounts.Description" = "Dibe ku tu bixwazî van hesaban bişopînî";
|
||||||
|
"Scene.Search.Recommend.Accounts.Follow" = "Bişopîne";
|
||||||
|
"Scene.Search.Recommend.Accounts.Title" = "Hesabên ku hûn dikarin hez bikin";
|
||||||
|
"Scene.Search.Recommend.ButtonText" = "Hemûyé bibîne";
|
||||||
|
"Scene.Search.Recommend.HashTag.Description" = "Etîketên ku pir balê dikişînin";
|
||||||
|
"Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ kes diaxivin";
|
||||||
|
"Scene.Search.Recommend.HashTag.Title" = "Trend li ser Mastodon";
|
||||||
|
"Scene.Search.SearchBar.Cancel" = "Betal kirin";
|
||||||
|
"Scene.Search.SearchBar.Placeholder" = "Li etîketan û bikarhêneran bigerin";
|
||||||
|
"Scene.Search.Searching.Clear" = "Paqij bike";
|
||||||
|
"Scene.Search.Searching.EmptyState.NoResults" = "Encam tune";
|
||||||
|
"Scene.Search.Searching.RecentSearch" = "Lêgerînên dawî";
|
||||||
|
"Scene.Search.Searching.Segment.All" = "Hemû";
|
||||||
|
"Scene.Search.Searching.Segment.Hashtags" = "Etîketan";
|
||||||
|
"Scene.Search.Searching.Segment.People" = "Mirov";
|
||||||
|
"Scene.Search.Searching.Segment.Posts" = "Şandîyan";
|
||||||
|
"Scene.Search.Title" = "Bigere";
|
||||||
|
"Scene.ServerPicker.Button.Category.Academia" = "akademî";
|
||||||
|
"Scene.ServerPicker.Button.Category.Activism" = "çalakî";
|
||||||
|
"Scene.ServerPicker.Button.Category.All" = "Hemû";
|
||||||
|
"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "Beş: Hemû";
|
||||||
|
"Scene.ServerPicker.Button.Category.Art" = "huner";
|
||||||
|
"Scene.ServerPicker.Button.Category.Food" = "xwarin";
|
||||||
|
"Scene.ServerPicker.Button.Category.Furry" = "furry";
|
||||||
|
"Scene.ServerPicker.Button.Category.Games" = "lîsk";
|
||||||
|
"Scene.ServerPicker.Button.Category.General" = "giştî";
|
||||||
|
"Scene.ServerPicker.Button.Category.Journalism" = "rojnamevanî";
|
||||||
|
"Scene.ServerPicker.Button.Category.Lgbt" = "lgbt";
|
||||||
|
"Scene.ServerPicker.Button.Category.Music" = "muzîk";
|
||||||
|
"Scene.ServerPicker.Button.Category.Regional" = "herêmî";
|
||||||
|
"Scene.ServerPicker.Button.Category.Tech" = "teknolojî";
|
||||||
|
"Scene.ServerPicker.Button.SeeLess" = "Kêmtir bibîne";
|
||||||
|
"Scene.ServerPicker.Button.SeeMore" = "Bêtir bibîne";
|
||||||
|
"Scene.ServerPicker.EmptyState.BadNetwork" = "Di dema barkirina daneyan da tiştek xelet derket. Girêdana xwe ya înternetê kontrol bike.";
|
||||||
|
"Scene.ServerPicker.EmptyState.FindingServers" = "Dîtina serverên berdest...";
|
||||||
|
"Scene.ServerPicker.EmptyState.NoResults" = "Encam nade";
|
||||||
|
"Scene.ServerPicker.Input.Placeholder" = "Serverek bibînin an jî beşdarî ya xwe bibin...";
|
||||||
|
"Scene.ServerPicker.Label.Category" = "KATEGORÎ";
|
||||||
|
"Scene.ServerPicker.Label.Language" = "ZIMAN";
|
||||||
|
"Scene.ServerPicker.Label.Users" = "BIKARHÊNER";
|
||||||
|
"Scene.ServerPicker.Title" = "Rajekarekê hilbijêre,
|
||||||
|
Her kîjan rajekar be.";
|
||||||
|
"Scene.ServerRules.Button.Confirm" = "Ez tev dibim";
|
||||||
|
"Scene.ServerRules.PrivacyPolicy" = "polîtîkaya nepenîtiyê";
|
||||||
|
"Scene.ServerRules.Prompt" = "Bi berdewamî, hûn ji bo %@ di bin şertên polîtîkaya xizmet û nepenîtiyê da ne.";
|
||||||
|
"Scene.ServerRules.Subtitle" = "Ev rêzik ji aliyê rêvebirên %@ ve tên sazkirin.";
|
||||||
|
"Scene.ServerRules.TermsOfService" = "şert û mercên xizmetê";
|
||||||
|
"Scene.ServerRules.Title" = "Hin qaîdeyên bingehîn.";
|
||||||
|
"Scene.Settings.Footer.MastodonDescription" = "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di %@ (%@) de";
|
||||||
|
"Scene.Settings.Keyboard.CloseSettingsWindow" = "Sazkariyên çarçoveyê bigire";
|
||||||
|
"Scene.Settings.Section.Appearance.Automatic" = "Xweber";
|
||||||
|
"Scene.Settings.Section.Appearance.Dark" = "Her dem tarî";
|
||||||
|
"Scene.Settings.Section.Appearance.Light" = "Her dem ronî";
|
||||||
|
"Scene.Settings.Section.Appearance.Title" = "Xuyang";
|
||||||
|
"Scene.Settings.Section.BoringZone.AccountSettings" = "Sazkariyên ajimêr";
|
||||||
|
"Scene.Settings.Section.BoringZone.Privacy" = "Polîtikaya nihêniyê";
|
||||||
|
"Scene.Settings.Section.BoringZone.Terms" = "Mercên bikaranînê";
|
||||||
|
"Scene.Settings.Section.BoringZone.Title" = "Devera acizker";
|
||||||
|
"Scene.Settings.Section.Notifications.Boosts" = "Şandiya min ji nû ve binivîsine";
|
||||||
|
"Scene.Settings.Section.Notifications.Favorites" = "Şandiyên min hez kir";
|
||||||
|
"Scene.Settings.Section.Notifications.Follows" = "Min şopand";
|
||||||
|
"Scene.Settings.Section.Notifications.Mentions" = "Qale min kir";
|
||||||
|
"Scene.Settings.Section.Notifications.Title" = "Agahdarî";
|
||||||
|
"Scene.Settings.Section.Notifications.Trigger.Anyone" = "her kes";
|
||||||
|
"Scene.Settings.Section.Notifications.Trigger.Follow" = "her kesê ku dişopînim";
|
||||||
|
"Scene.Settings.Section.Notifications.Trigger.Follower" = "şopînerek";
|
||||||
|
"Scene.Settings.Section.Notifications.Trigger.Noone" = "ne yek";
|
||||||
|
"Scene.Settings.Section.Notifications.Trigger.Title" = "Min agahdar bike gava";
|
||||||
|
"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "Avatarên anîmasyonî neçalak bike";
|
||||||
|
"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "Emojiyên anîmasyonî neçalak bike";
|
||||||
|
"Scene.Settings.Section.Preference.Title" = "Hilbijarte";
|
||||||
|
"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "Moda tarî ya reş a rastîn";
|
||||||
|
"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "Ji bo vekirina girêdanan geroka berdest bi kar bîne";
|
||||||
|
"Scene.Settings.Section.SpicyZone.Clear" = "Pêşbîra medyayê pak bike";
|
||||||
|
"Scene.Settings.Section.SpicyZone.Signout" = "Derkeve";
|
||||||
|
"Scene.Settings.Section.SpicyZone.Title" = "Devera germ";
|
||||||
|
"Scene.Settings.Title" = "Sazkarî";
|
||||||
|
"Scene.SuggestionAccount.FollowExplain" = "Gava tu kesekî dişopînî, tu yê şandiyê wan di serrûpelê de bibîne.";
|
||||||
|
"Scene.SuggestionAccount.Title" = "Kesên bo ku bişopînî bibîne";
|
||||||
|
"Scene.Thread.BackTitle" = "Şandî";
|
||||||
|
"Scene.Thread.Title" = "Şandî ji %@";
|
||||||
|
"Scene.Welcome.Slogan" = "Torên civakî
|
||||||
|
di destên te de.";
|
||||||
|
"Scene.Wizard.AccessibilityHint" = "Du caran bitikîne da ku çarçoveyahilpekok ji holê rakî";
|
||||||
|
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Dest bide ser bişkoja profîlê da ku di navbera gelek ajimêrann de biguherînî.";
|
||||||
|
"Scene.Wizard.NewInMastodon" = "Nû di Mastodon de";
|
|
@ -0,0 +1,390 @@
|
||||||
|
<?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>a11y.plural.count.unread.notification</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@notification_count_unread_notification@</string>
|
||||||
|
<key>notification_count_unread_notification</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 agahdariya nexwendî</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld agahdariyên nexwendî</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>a11y.plural.count.input_limit_exceeds</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>Sînorê têketinê derbas kir %#@character_count@</string>
|
||||||
|
<key>character_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 tîp</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld tîp</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>a11y.plural.count.input_limit_remains</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>Sînorê têketinê %#@character_count@ maye</string>
|
||||||
|
<key>character_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 tîp</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld tîp</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.metric_formatted.post</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%@ %#@post_count@</string>
|
||||||
|
<key>post_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>şandî</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>şandî</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.post</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@post_count@</string>
|
||||||
|
<key>post_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 şandî</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld şandî</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.favorite</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@favorite_count@</string>
|
||||||
|
<key>favorite_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 hezkirin</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld hezkirin</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.reblog</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@reblog_count@</string>
|
||||||
|
<key>reblog_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 ji nû ve nivîsandin</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld ji nû ve nivîsandin</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.vote</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@vote_count@</string>
|
||||||
|
<key>vote_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 deng</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld deng</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.voter</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@voter_count@</string>
|
||||||
|
<key>voter_count</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 hilbijêr</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld hilbijêr</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.people_talking</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_people_talking@</string>
|
||||||
|
<key>count_people_talking</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 mirov diaxive</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld mirov diaxive</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.following</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_following@</string>
|
||||||
|
<key>count_following</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 dişopîne</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld dişopîne</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>plural.count.follower</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_follower@</string>
|
||||||
|
<key>count_follower</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 şopîner</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld şopîner</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.year.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_year_left@</string>
|
||||||
|
<key>count_year_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 sal berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld sal berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.month.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_month_left@</string>
|
||||||
|
<key>count_month_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 meh berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld meh berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.day.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_day_left@</string>
|
||||||
|
<key>count_day_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 roj berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld roj berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.hour.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_hour_left@</string>
|
||||||
|
<key>count_hour_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 demjimêr berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld demjimêr berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.minute.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_minute_left@</string>
|
||||||
|
<key>count_minute_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 xulek berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld xulek berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.second.left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_second_left@</string>
|
||||||
|
<key>count_second_left</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 çirke berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld çirke berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.year.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_year_ago_abbr@</string>
|
||||||
|
<key>count_year_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 sal berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld sal berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.month.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_month_ago_abbr@</string>
|
||||||
|
<key>count_month_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 xulek berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld xulek berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.day.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_day_ago_abbr@</string>
|
||||||
|
<key>count_day_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 roj berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld roj berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.hour.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_hour_ago_abbr@</string>
|
||||||
|
<key>count_hour_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 demjimêr berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld demjimêr berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.minute.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_minute_ago_abbr@</string>
|
||||||
|
<key>count_minute_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 xulek berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld xulek berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>date.second.ago.abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@count_second_ago_abbr@</string>
|
||||||
|
<key>count_second_ago_abbr</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>ld</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>1 çirke berê</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>%ld çirke berê</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -27,6 +27,7 @@
|
||||||
"Common.Controls.Actions.Back" = "Terug";
|
"Common.Controls.Actions.Back" = "Terug";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Blokkeer %@";
|
"Common.Controls.Actions.BlockDomain" = "Blokkeer %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Annuleren";
|
"Common.Controls.Actions.Cancel" = "Annuleren";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Bevestigen";
|
"Common.Controls.Actions.Confirm" = "Bevestigen";
|
||||||
"Common.Controls.Actions.Continue" = "Doorgaan";
|
"Common.Controls.Actions.Continue" = "Doorgaan";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Foto kopiëren";
|
"Common.Controls.Actions.CopyPhoto" = "Foto kopiëren";
|
||||||
|
@ -184,6 +185,8 @@ Uw profiel ziet er zo uit voor hen.";
|
||||||
klik op de link om uw account te bevestigen.";
|
klik op de link om uw account te bevestigen.";
|
||||||
"Scene.ConfirmEmail.Title" = "Nog één ding.";
|
"Scene.ConfirmEmail.Title" = "Nog één ding.";
|
||||||
"Scene.Favorite.Title" = "Uw favorieten";
|
"Scene.Favorite.Title" = "Uw favorieten";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Bekijk nieuwe berichten";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Bekijk nieuwe berichten";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Gepubliceerd!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Gepubliceerd!";
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"Common.Controls.Actions.Back" = "Назад";
|
"Common.Controls.Actions.Back" = "Назад";
|
||||||
"Common.Controls.Actions.BlockDomain" = "Заблокировать %@";
|
"Common.Controls.Actions.BlockDomain" = "Заблокировать %@";
|
||||||
"Common.Controls.Actions.Cancel" = "Отмена";
|
"Common.Controls.Actions.Cancel" = "Отмена";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "Подтвердить";
|
"Common.Controls.Actions.Confirm" = "Подтвердить";
|
||||||
"Common.Controls.Actions.Continue" = "Продолжить";
|
"Common.Controls.Actions.Continue" = "Продолжить";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "Скопировать изображение";
|
"Common.Controls.Actions.CopyPhoto" = "Скопировать изображение";
|
||||||
|
@ -200,6 +201,8 @@
|
||||||
подтвердить свою учётную запись.";
|
подтвердить свою учётную запись.";
|
||||||
"Scene.ConfirmEmail.Title" = "И ещё кое-что.";
|
"Scene.ConfirmEmail.Title" = "И ещё кое-что.";
|
||||||
"Scene.Favorite.Title" = "Ваше избранное";
|
"Scene.Favorite.Title" = "Ваше избранное";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Показать новые";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Показать новые";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "Не в сети";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "Не в сети";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "Опубликовано!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "Опубликовано!";
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"Common.Controls.Actions.Back" = "ย้อนกลับ";
|
"Common.Controls.Actions.Back" = "ย้อนกลับ";
|
||||||
"Common.Controls.Actions.BlockDomain" = "ปิดกั้น %@";
|
"Common.Controls.Actions.BlockDomain" = "ปิดกั้น %@";
|
||||||
"Common.Controls.Actions.Cancel" = "ยกเลิก";
|
"Common.Controls.Actions.Cancel" = "ยกเลิก";
|
||||||
|
"Common.Controls.Actions.Compose" = "Compose";
|
||||||
"Common.Controls.Actions.Confirm" = "ยืนยัน";
|
"Common.Controls.Actions.Confirm" = "ยืนยัน";
|
||||||
"Common.Controls.Actions.Continue" = "ดำเนินการต่อ";
|
"Common.Controls.Actions.Continue" = "ดำเนินการต่อ";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "คัดลอกรูปภาพ";
|
"Common.Controls.Actions.CopyPhoto" = "คัดลอกรูปภาพ";
|
||||||
|
@ -190,6 +191,8 @@
|
||||||
แตะที่ลิงก์เพื่อยืนยันบัญชีของคุณ";
|
แตะที่ลิงก์เพื่อยืนยันบัญชีของคุณ";
|
||||||
"Scene.ConfirmEmail.Title" = "หนึ่งสิ่งสุดท้าย";
|
"Scene.ConfirmEmail.Title" = "หนึ่งสิ่งสุดท้าย";
|
||||||
"Scene.Favorite.Title" = "รายการโปรดของคุณ";
|
"Scene.Favorite.Title" = "รายการโปรดของคุณ";
|
||||||
|
"Scene.Follower.Footer" = "Followers from other servers are not displayed.";
|
||||||
|
"Scene.Following.Footer" = "Follows from other servers are not displayed.";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "ดูโพสต์ใหม่";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "ดูโพสต์ใหม่";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "ออฟไลน์";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "ออฟไลน์";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "เผยแพร่แล้ว!";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "เผยแพร่แล้ว!";
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"Common.Controls.Actions.Back" = "返回";
|
"Common.Controls.Actions.Back" = "返回";
|
||||||
"Common.Controls.Actions.BlockDomain" = "屏蔽 %@";
|
"Common.Controls.Actions.BlockDomain" = "屏蔽 %@";
|
||||||
"Common.Controls.Actions.Cancel" = "取消";
|
"Common.Controls.Actions.Cancel" = "取消";
|
||||||
|
"Common.Controls.Actions.Compose" = "撰写";
|
||||||
"Common.Controls.Actions.Confirm" = "确认";
|
"Common.Controls.Actions.Confirm" = "确认";
|
||||||
"Common.Controls.Actions.Continue" = "继续";
|
"Common.Controls.Actions.Continue" = "继续";
|
||||||
"Common.Controls.Actions.CopyPhoto" = "拷贝照片";
|
"Common.Controls.Actions.CopyPhoto" = "拷贝照片";
|
||||||
|
@ -190,6 +191,8 @@
|
||||||
点击链接确认你的帐户。";
|
点击链接确认你的帐户。";
|
||||||
"Scene.ConfirmEmail.Title" = "最后一件事。";
|
"Scene.ConfirmEmail.Title" = "最后一件事。";
|
||||||
"Scene.Favorite.Title" = "你的喜欢";
|
"Scene.Favorite.Title" = "你的喜欢";
|
||||||
|
"Scene.Follower.Footer" = "不会显示来自其它服务器的关注者";
|
||||||
|
"Scene.Following.Footer" = "不会显示来自其它服务器的关注";
|
||||||
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "查看新帖子";
|
"Scene.HomeTimeline.NavigationBarState.NewPosts" = "查看新帖子";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Offline" = "离线";
|
"Scene.HomeTimeline.NavigationBarState.Offline" = "离线";
|
||||||
"Scene.HomeTimeline.NavigationBarState.Published" = "已发送";
|
"Scene.HomeTimeline.NavigationBarState.Published" = "已发送";
|
||||||
|
|
|
@ -9,7 +9,7 @@ import UIKit
|
||||||
import MetaTextKit
|
import MetaTextKit
|
||||||
|
|
||||||
final class AddAccountTableViewCell: UITableViewCell {
|
final class AddAccountTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
let iconImageView: UIImageView = {
|
let iconImageView: UIImageView = {
|
||||||
let image = UIImage(systemName: "plus.circle.fill")!
|
let image = UIImage(systemName: "plus.circle.fill")!
|
||||||
let imageView = UIImageView(image: image)
|
let imageView = UIImageView(image: image)
|
||||||
|
@ -51,6 +51,28 @@ extension AddAccountTableViewCell {
|
||||||
])
|
])
|
||||||
iconImageView.setContentHuggingPriority(.defaultLow, for: .horizontal)
|
iconImageView.setContentHuggingPriority(.defaultLow, for: .horizontal)
|
||||||
iconImageView.setContentHuggingPriority(.defaultLow, for: .vertical)
|
iconImageView.setContentHuggingPriority(.defaultLow, for: .vertical)
|
||||||
|
|
||||||
|
// layout the same placeholder UI from `AccountListTableViewCell`
|
||||||
|
let placeholderLabelContainerStackView = UIStackView()
|
||||||
|
placeholderLabelContainerStackView.axis = .vertical
|
||||||
|
placeholderLabelContainerStackView.distribution = .equalCentering
|
||||||
|
placeholderLabelContainerStackView.spacing = 2
|
||||||
|
placeholderLabelContainerStackView.distribution = .fillProportionally
|
||||||
|
placeholderLabelContainerStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
contentView.addSubview(placeholderLabelContainerStackView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
placeholderLabelContainerStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
|
||||||
|
placeholderLabelContainerStackView.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 10),
|
||||||
|
contentView.bottomAnchor.constraint(equalTo: placeholderLabelContainerStackView.bottomAnchor, constant: 10),
|
||||||
|
iconImageView.heightAnchor.constraint(equalTo: placeholderLabelContainerStackView.heightAnchor, multiplier: 0.8).priority(.required - 10),
|
||||||
|
])
|
||||||
|
let _nameLabel = MetaLabel(style: .accountListName)
|
||||||
|
_nameLabel.configure(content: PlaintextMetaContent(string: " "))
|
||||||
|
let _usernameLabel = MetaLabel(style: .accountListUsername)
|
||||||
|
_usernameLabel.configure(content: PlaintextMetaContent(string: " "))
|
||||||
|
placeholderLabelContainerStackView.addArrangedSubview(_nameLabel)
|
||||||
|
placeholderLabelContainerStackView.addArrangedSubview(_usernameLabel)
|
||||||
|
placeholderLabelContainerStackView.isHidden = true
|
||||||
|
|
||||||
titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
contentView.addSubview(titleLabel)
|
contentView.addSubview(titleLabel)
|
||||||
|
@ -58,7 +80,7 @@ extension AddAccountTableViewCell {
|
||||||
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 15),
|
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 15),
|
||||||
titleLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 10),
|
titleLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 10),
|
||||||
contentView.bottomAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 15),
|
contentView.bottomAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 15),
|
||||||
iconImageView.heightAnchor.constraint(equalTo: titleLabel.heightAnchor, multiplier: 1.0).priority(.required - 10),
|
// iconImageView.heightAnchor.constraint(equalTo: titleLabel.heightAnchor, multiplier: 1.0).priority(.required - 10),
|
||||||
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
|
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ extension ComposeToolbarView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func configureToolbarButtonAppearance(button: UIButton) {
|
private static func configureToolbarButtonAppearance(button: UIButton) {
|
||||||
button.tintColor = Asset.Colors.brandBlue.color
|
button.tintColor = ThemeService.tintColor
|
||||||
button.setBackgroundImage(.placeholder(size: ComposeToolbarView.toolbarButtonSize, color: .systemFill), for: .highlighted)
|
button.setBackgroundImage(.placeholder(size: ComposeToolbarView.toolbarButtonSize, color: .systemFill), for: .highlighted)
|
||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
button.layer.cornerRadius = 5
|
button.layer.cornerRadius = 5
|
||||||
|
|
|
@ -24,7 +24,7 @@ class HashtagTimelineViewController: UIViewController, NeedsDependency, MediaPre
|
||||||
|
|
||||||
let composeBarButtonItem: UIBarButtonItem = {
|
let composeBarButtonItem: UIBarButtonItem = {
|
||||||
let barButtonItem = UIBarButtonItem()
|
let barButtonItem = UIBarButtonItem()
|
||||||
barButtonItem.tintColor = Asset.Colors.brandBlue.color
|
// barButtonItem.tintColor = Asset.Colors.brandBlue.color
|
||||||
barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate)
|
barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate)
|
||||||
return barButtonItem
|
return barButtonItem
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -15,6 +15,7 @@ import FLEX
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import MastodonUI
|
import MastodonUI
|
||||||
import MastodonSDK
|
import MastodonSDK
|
||||||
|
import StoreKit
|
||||||
|
|
||||||
extension HomeTimelineViewController {
|
extension HomeTimelineViewController {
|
||||||
var debugMenu: UIMenu {
|
var debugMenu: UIMenu {
|
||||||
|
@ -77,6 +78,11 @@ extension HomeTimelineViewController {
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.showThreadAction(action)
|
self.showThreadAction(action)
|
||||||
},
|
},
|
||||||
|
UIAction(title: "Store Rating", image: UIImage(systemName: "star.fill"), attributes: []) { [weak self] action in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let windowScene = self.view.window?.windowScene else { return }
|
||||||
|
SKStoreReviewController.requestReview(in: windowScene)
|
||||||
|
},
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import CoreDataStack
|
||||||
import GameplayKit
|
import GameplayKit
|
||||||
import MastodonSDK
|
import MastodonSDK
|
||||||
import AlamofireImage
|
import AlamofireImage
|
||||||
|
import StoreKit
|
||||||
|
|
||||||
final class HomeTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
final class HomeTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||||
|
|
||||||
|
@ -46,14 +47,14 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media
|
||||||
|
|
||||||
let settingBarButtonItem: UIBarButtonItem = {
|
let settingBarButtonItem: UIBarButtonItem = {
|
||||||
let barButtonItem = UIBarButtonItem()
|
let barButtonItem = UIBarButtonItem()
|
||||||
barButtonItem.tintColor = Asset.Colors.brandBlue.color
|
barButtonItem.tintColor = ThemeService.tintColor
|
||||||
barButtonItem.image = UIImage(systemName: "gear")?.withRenderingMode(.alwaysTemplate)
|
barButtonItem.image = UIImage(systemName: "gear")?.withRenderingMode(.alwaysTemplate)
|
||||||
return barButtonItem
|
return barButtonItem
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let composeBarButtonItem: UIBarButtonItem = {
|
let composeBarButtonItem: UIBarButtonItem = {
|
||||||
let barButtonItem = UIBarButtonItem()
|
let barButtonItem = UIBarButtonItem()
|
||||||
barButtonItem.tintColor = Asset.Colors.brandBlue.color
|
barButtonItem.tintColor = ThemeService.tintColor
|
||||||
barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate)
|
barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate)
|
||||||
return barButtonItem
|
return barButtonItem
|
||||||
}()
|
}()
|
||||||
|
@ -144,6 +145,21 @@ extension HomeTimelineViewController {
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
viewModel.homeTimelineNavigationBarTitleViewModel.state
|
||||||
|
.removeDuplicates()
|
||||||
|
.filter { $0 == .publishedButton }
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard UserDefaults.shared.lastVersionPromptedForReview == nil else { return }
|
||||||
|
guard UserDefaults.shared.processCompletedCount > 3 else { return }
|
||||||
|
guard let windowScene = self.view.window?.windowScene else { return }
|
||||||
|
let version = UIApplication.appVersion()
|
||||||
|
UserDefaults.shared.lastVersionPromptedForReview = version
|
||||||
|
SKStoreReviewController.requestReview(in: windowScene)
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
tableView.refreshControl = refreshControl
|
tableView.refreshControl = refreshControl
|
||||||
refreshControl.addTarget(self, action: #selector(HomeTimelineViewController.refreshControlValueChanged(_:)), for: .valueChanged)
|
refreshControl.addTarget(self, action: #selector(HomeTimelineViewController.refreshControlValueChanged(_:)), for: .valueChanged)
|
||||||
|
|
||||||
|
|
|
@ -19,21 +19,25 @@ extension NotificationViewController: StatusProvider {
|
||||||
|
|
||||||
func status(for cell: UITableViewCell?, indexPath: IndexPath?) -> Future<Status?, Never> {
|
func status(for cell: UITableViewCell?, indexPath: IndexPath?) -> Future<Status?, Never> {
|
||||||
return Future<Status?, Never> { promise in
|
return Future<Status?, Never> { promise in
|
||||||
guard let cell = cell,
|
guard let diffableDataSource = self.viewModel.diffableDataSource else {
|
||||||
let diffableDataSource = self.viewModel.diffableDataSource,
|
assertionFailure()
|
||||||
let indexPath = self.tableView.indexPath(for: cell),
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let indexPath = indexPath ?? cell.flatMap({ self.tableView.indexPath(for: $0) }),
|
||||||
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
|
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
|
||||||
promise(.success(nil))
|
promise(.success(nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch item {
|
switch item {
|
||||||
case .notification(let objectID, _):
|
case .notification(let objectID, _),
|
||||||
|
.notificationStatus(let objectID, _):
|
||||||
self.viewModel.fetchedResultsController.managedObjectContext.perform {
|
self.viewModel.fetchedResultsController.managedObjectContext.perform {
|
||||||
let notification = self.viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! MastodonNotification
|
let notification = self.viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! MastodonNotification
|
||||||
promise(.success(notification.status))
|
promise(.success(notification.status))
|
||||||
}
|
}
|
||||||
default:
|
case .bottomLoader:
|
||||||
promise(.success(nil))
|
promise(.success(nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,3 +72,6 @@ extension NotificationViewController: StatusProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - UserProvider
|
||||||
|
extension NotificationViewController: UserProvider { }
|
||||||
|
|
|
@ -14,8 +14,10 @@ import OSLog
|
||||||
import UIKit
|
import UIKit
|
||||||
import Meta
|
import Meta
|
||||||
import MetaTextKit
|
import MetaTextKit
|
||||||
|
import AVKit
|
||||||
|
|
||||||
final class NotificationViewController: UIViewController, NeedsDependency {
|
final class NotificationViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||||
|
|
||||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
||||||
|
@ -23,15 +25,18 @@ final class NotificationViewController: UIViewController, NeedsDependency {
|
||||||
var observations = Set<NSKeyValueObservation>()
|
var observations = Set<NSKeyValueObservation>()
|
||||||
|
|
||||||
private(set) lazy var viewModel = NotificationViewModel(context: context)
|
private(set) lazy var viewModel = NotificationViewModel(context: context)
|
||||||
|
|
||||||
|
let mediaPreviewTransitionController = MediaPreviewTransitionController()
|
||||||
|
|
||||||
let segmentControl: UISegmentedControl = {
|
let segmentControl: UISegmentedControl = {
|
||||||
let control = UISegmentedControl(items: [L10n.Scene.Notification.Title.everything, L10n.Scene.Notification.Title.mentions])
|
let control = UISegmentedControl(items: [L10n.Scene.Notification.Title.everything, L10n.Scene.Notification.Title.mentions])
|
||||||
control.selectedSegmentIndex = NotificationViewModel.NotificationSegment.EveryThing.rawValue
|
control.selectedSegmentIndex = NotificationViewModel.NotificationSegment.everyThing.rawValue
|
||||||
return control
|
return control
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let tableView: UITableView = {
|
let tableView: UITableView = {
|
||||||
let tableView = ControlContainableTableView()
|
let tableView = ControlContainableTableView()
|
||||||
|
tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self))
|
||||||
tableView.register(NotificationStatusTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationStatusTableViewCell.self))
|
tableView.register(NotificationStatusTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationStatusTableViewCell.self))
|
||||||
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
|
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
|
||||||
tableView.estimatedRowHeight = UITableView.automaticDimension
|
tableView.estimatedRowHeight = UITableView.automaticDimension
|
||||||
|
@ -82,7 +87,12 @@ extension NotificationViewController {
|
||||||
tableView.delegate = self
|
tableView.delegate = self
|
||||||
viewModel.tableView = tableView
|
viewModel.tableView = tableView
|
||||||
viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self
|
viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self
|
||||||
viewModel.setupDiffableDataSource(for: tableView, delegate: self, dependency: self)
|
viewModel.setupDiffableDataSource(
|
||||||
|
for: tableView,
|
||||||
|
dependency: self,
|
||||||
|
delegate: self,
|
||||||
|
statusTableViewCellDelegate: self
|
||||||
|
)
|
||||||
viewModel.viewDidLoad.send()
|
viewModel.viewDidLoad.send()
|
||||||
|
|
||||||
// bind refresh control
|
// bind refresh control
|
||||||
|
@ -128,9 +138,9 @@ extension NotificationViewController {
|
||||||
self.viewModel.needsScrollToTopAfterDataSourceUpdate = true
|
self.viewModel.needsScrollToTopAfterDataSourceUpdate = true
|
||||||
|
|
||||||
switch segment {
|
switch segment {
|
||||||
case .EveryThing:
|
case .everyThing:
|
||||||
self.viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID)
|
self.viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID)
|
||||||
case .Mentions:
|
case .mentions:
|
||||||
self.viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID, typeRaw: Mastodon.Entity.Notification.NotificationType.mention.rawValue)
|
self.viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID, typeRaw: Mastodon.Entity.Notification.NotificationType.mention.rawValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,8 +158,8 @@ extension NotificationViewController {
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
tableView.deselectRow(with: transitionCoordinator, animated: animated)
|
aspectViewWillAppear(animated)
|
||||||
|
|
||||||
// fetch latest notification when scroll position is within half screen height to prevent list reload
|
// fetch latest notification when scroll position is within half screen height to prevent list reload
|
||||||
if tableView.contentOffset.y < view.frame.height * 0.5 {
|
if tableView.contentOffset.y < view.frame.height * 0.5 {
|
||||||
|
@ -181,6 +191,12 @@ extension NotificationViewController {
|
||||||
// reset notification count
|
// reset notification count
|
||||||
context.notificationService.clearNotificationCountForActiveUser()
|
context.notificationService.clearNotificationCountForActiveUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
|
super.viewDidDisappear(animated)
|
||||||
|
|
||||||
|
aspectViewDidDisappear(animated)
|
||||||
|
}
|
||||||
|
|
||||||
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||||
super.viewWillTransition(to: size, with: coordinator)
|
super.viewWillTransition(to: size, with: coordinator)
|
||||||
|
@ -208,33 +224,34 @@ extension NotificationViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - StatusTableViewControllerAspect
|
// MARK: - TableViewCellHeightCacheableContainer
|
||||||
extension NotificationViewController: StatusTableViewControllerAspect { }
|
extension NotificationViewController: TableViewCellHeightCacheableContainer {
|
||||||
|
var cellFrameCache: NSCache<NSNumber, NSValue> { return viewModel.cellFrameCache }
|
||||||
extension NotificationViewController {
|
|
||||||
|
|
||||||
func cacheTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
func cacheTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
||||||
switch item {
|
switch item {
|
||||||
case .notification(let objectID, _):
|
case .notification(let objectID, _),
|
||||||
|
.notificationStatus(let objectID, _):
|
||||||
guard let object = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return }
|
guard let object = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return }
|
||||||
let key = object.id as NSString
|
let key = object.objectID.hashValue
|
||||||
let frame = cell.frame
|
let frame = cell.frame
|
||||||
viewModel.cellFrameCache.setObject(NSValue(cgRect: frame), forKey: key)
|
viewModel.cellFrameCache.setObject(NSValue(cgRect: frame), forKey: NSNumber(value: key))
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleTableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
func handleTableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
guard let diffableDataSource = viewModel.diffableDataSource else { return UITableView.automaticDimension }
|
guard let diffableDataSource = viewModel.diffableDataSource else { return UITableView.automaticDimension }
|
||||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return UITableView.automaticDimension }
|
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return UITableView.automaticDimension }
|
||||||
switch item {
|
switch item {
|
||||||
case .notification(let objectID, _):
|
case .notification(let objectID, _),
|
||||||
|
.notificationStatus(let objectID, _):
|
||||||
guard let object = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return UITableView.automaticDimension }
|
guard let object = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return UITableView.automaticDimension }
|
||||||
let key = object.id as NSString
|
let key = object.objectID.hashValue
|
||||||
guard let frame = viewModel.cellFrameCache.object(forKey: key)?.cgRectValue else { return UITableView.automaticDimension }
|
guard let frame = viewModel.cellFrameCache.object(forKey: NSNumber(value: key))?.cgRectValue else { return UITableView.automaticDimension }
|
||||||
return frame.height
|
return frame.height
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
return TimelineLoaderTableViewCell.cellHeight
|
return TimelineLoaderTableViewCell.cellHeight
|
||||||
|
@ -242,22 +259,55 @@ extension NotificationViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - StatusTableViewControllerAspect
|
||||||
|
extension NotificationViewController: StatusTableViewControllerAspect { }
|
||||||
|
|
||||||
// MARK: - UITableViewDelegate
|
// MARK: - UITableViewDelegate
|
||||||
|
|
||||||
extension NotificationViewController: UITableViewDelegate {
|
extension NotificationViewController: UITableViewDelegate {
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
|
aspectTableView(tableView, estimatedHeightForRowAt: indexPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
||||||
open(item: item)
|
switch item {
|
||||||
|
case .notificationStatus:
|
||||||
|
aspectTableView(tableView, willDisplay: cell, forRowAt: indexPath)
|
||||||
|
case .bottomLoader:
|
||||||
|
if !tableView.isDragging, !tableView.isDecelerating {
|
||||||
|
viewModel.loadOldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||||
cacheTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath)
|
aspectTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
aspectTableView(tableView, didSelectRowAt: indexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
|
||||||
return handleTableView(tableView, estimatedHeightForRowAt: indexPath)
|
return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||||
|
return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||||
|
return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
|
||||||
|
aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -278,19 +328,6 @@ extension NotificationViewController {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
|
||||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
|
||||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
|
||||||
switch item {
|
|
||||||
case .bottomLoader:
|
|
||||||
if !tableView.isDragging, !tableView.isDecelerating {
|
|
||||||
viewModel.loadOldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate
|
// MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate
|
||||||
|
@ -388,6 +425,7 @@ extension NotificationViewController: ScrollViewContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - LoadMoreConfigurableTableViewContainer
|
||||||
extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
|
extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
|
||||||
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
|
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
|
||||||
typealias LoadingState = NotificationViewModel.LoadOldestState.Loading
|
typealias LoadingState = NotificationViewModel.LoadOldestState.Loading
|
||||||
|
@ -395,6 +433,24 @@ extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
|
||||||
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadOldestStateMachine }
|
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadOldestStateMachine }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - AVPlayerViewControllerDelegate
|
||||||
|
extension NotificationViewController: AVPlayerViewControllerDelegate {
|
||||||
|
func playerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
|
||||||
|
handlePlayerViewController(playerViewController, willBeginFullScreenPresentationWithAnimationCoordinator: coordinator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
|
||||||
|
handlePlayerViewController(playerViewController, willEndFullScreenPresentationWithAnimationCoordinator: coordinator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - statusTableViewCellDelegate
|
||||||
|
extension NotificationViewController: StatusTableViewCellDelegate {
|
||||||
|
var playerViewControllerDelegate: AVPlayerViewControllerDelegate? {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension NotificationViewController {
|
extension NotificationViewController {
|
||||||
|
|
||||||
enum CategorySwitch: String, CaseIterable {
|
enum CategorySwitch: String, CaseIterable {
|
||||||
|
@ -452,9 +508,9 @@ extension NotificationViewController {
|
||||||
|
|
||||||
switch category {
|
switch category {
|
||||||
case .showEverything:
|
case .showEverything:
|
||||||
viewModel.selectedIndex.value = .EveryThing
|
viewModel.selectedIndex.value = .everyThing
|
||||||
case .showMentions:
|
case .showMentions:
|
||||||
viewModel.selectedIndex.value = .Mentions
|
viewModel.selectedIndex.value = .mentions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,16 @@ import MastodonSDK
|
||||||
extension NotificationViewModel {
|
extension NotificationViewModel {
|
||||||
func setupDiffableDataSource(
|
func setupDiffableDataSource(
|
||||||
for tableView: UITableView,
|
for tableView: UITableView,
|
||||||
|
dependency: NeedsDependency,
|
||||||
delegate: NotificationTableViewCellDelegate,
|
delegate: NotificationTableViewCellDelegate,
|
||||||
dependency: NeedsDependency
|
statusTableViewCellDelegate: StatusTableViewCellDelegate
|
||||||
) {
|
) {
|
||||||
diffableDataSource = NotificationSection.tableViewDiffableDataSource(
|
diffableDataSource = NotificationSection.tableViewDiffableDataSource(
|
||||||
for: tableView,
|
for: tableView,
|
||||||
|
dependency: dependency,
|
||||||
managedObjectContext: fetchedResultsController.managedObjectContext,
|
managedObjectContext: fetchedResultsController.managedObjectContext,
|
||||||
delegate: delegate,
|
delegate: delegate,
|
||||||
dependency: dependency
|
statusTableViewCellDelegate: statusTableViewCellDelegate
|
||||||
)
|
)
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<NotificationSection, NotificationItem>()
|
var snapshot = NSDiffableDataSourceSnapshot<NotificationSection, NotificationItem>()
|
||||||
|
@ -81,11 +83,23 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate {
|
||||||
}
|
}
|
||||||
var newSnapshot = NSDiffableDataSourceSnapshot<NotificationSection, NotificationItem>()
|
var newSnapshot = NSDiffableDataSourceSnapshot<NotificationSection, NotificationItem>()
|
||||||
newSnapshot.appendSections([.main])
|
newSnapshot.appendSections([.main])
|
||||||
let items: [NotificationItem] = notifications.map { notification in
|
|
||||||
let attribute: Item.StatusAttribute = oldSnapshotAttributeDict[notification.objectID] ?? Item.StatusAttribute()
|
let segment = self.selectedIndex.value
|
||||||
return NotificationItem.notification(objectID: notification.objectID, attribute: attribute)
|
switch segment {
|
||||||
|
case .everyThing:
|
||||||
|
let items: [NotificationItem] = notifications.map { notification in
|
||||||
|
let attribute: Item.StatusAttribute = oldSnapshotAttributeDict[notification.objectID] ?? Item.StatusAttribute()
|
||||||
|
return NotificationItem.notification(objectID: notification.objectID, attribute: attribute)
|
||||||
|
}
|
||||||
|
newSnapshot.appendItems(items, toSection: .main)
|
||||||
|
case .mentions:
|
||||||
|
let items: [NotificationItem] = notifications.map { notification in
|
||||||
|
let attribute: Item.StatusAttribute = oldSnapshotAttributeDict[notification.objectID] ?? Item.StatusAttribute()
|
||||||
|
return NotificationItem.notificationStatus(objectID: notification.objectID, attribute: attribute)
|
||||||
|
}
|
||||||
|
newSnapshot.appendItems(items, toSection: .main)
|
||||||
}
|
}
|
||||||
newSnapshot.appendItems(items, toSection: .main)
|
|
||||||
if !notifications.isEmpty, self.noMoreNotification.value == false {
|
if !notifications.isEmpty, self.noMoreNotification.value == false {
|
||||||
newSnapshot.appendItems([.bottomLoader], toSection: .main)
|
newSnapshot.appendItems([.bottomLoader], toSection: .main)
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,13 +92,13 @@ extension NotificationViewModel.LoadOldestState {
|
||||||
} receiveValue: { [weak viewModel] response in
|
} receiveValue: { [weak viewModel] response in
|
||||||
guard let viewModel = viewModel else { return }
|
guard let viewModel = viewModel else { return }
|
||||||
switch viewModel.selectedIndex.value {
|
switch viewModel.selectedIndex.value {
|
||||||
case .EveryThing:
|
case .everyThing:
|
||||||
if response.value.isEmpty {
|
if response.value.isEmpty {
|
||||||
stateMachine.enter(NoMore.self)
|
stateMachine.enter(NoMore.self)
|
||||||
} else {
|
} else {
|
||||||
stateMachine.enter(Idle.self)
|
stateMachine.enter(Idle.self)
|
||||||
}
|
}
|
||||||
case .Mentions:
|
case .mentions:
|
||||||
viewModel.noMoreNotification.value = response.value.isEmpty
|
viewModel.noMoreNotification.value = response.value.isEmpty
|
||||||
let list = response.value.filter { $0.type == Mastodon.Entity.Notification.NotificationType.mention }
|
let list = response.value.filter { $0.type == Mastodon.Entity.Notification.NotificationType.mention }
|
||||||
if list.isEmpty {
|
if list.isEmpty {
|
||||||
|
|
|
@ -23,13 +23,13 @@ final class NotificationViewModel: NSObject {
|
||||||
weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate?
|
weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate?
|
||||||
|
|
||||||
let viewDidLoad = PassthroughSubject<Void, Never>()
|
let viewDidLoad = PassthroughSubject<Void, Never>()
|
||||||
let selectedIndex = CurrentValueSubject<NotificationSegment, Never>(.EveryThing)
|
let selectedIndex = CurrentValueSubject<NotificationSegment, Never>(.everyThing)
|
||||||
let noMoreNotification = CurrentValueSubject<Bool, Never>(false)
|
let noMoreNotification = CurrentValueSubject<Bool, Never>(false)
|
||||||
|
|
||||||
let activeMastodonAuthenticationBox: CurrentValueSubject<MastodonAuthenticationBox?, Never>
|
let activeMastodonAuthenticationBox: CurrentValueSubject<MastodonAuthenticationBox?, Never>
|
||||||
let fetchedResultsController: NSFetchedResultsController<MastodonNotification>!
|
let fetchedResultsController: NSFetchedResultsController<MastodonNotification>!
|
||||||
let notificationPredicate = CurrentValueSubject<NSPredicate?, Never>(nil)
|
let notificationPredicate = CurrentValueSubject<NSPredicate?, Never>(nil)
|
||||||
let cellFrameCache = NSCache<NSString, NSValue>()
|
let cellFrameCache = NSCache<NSNumber, NSValue>()
|
||||||
|
|
||||||
var needsScrollToTopAfterDataSourceUpdate = false
|
var needsScrollToTopAfterDataSourceUpdate = false
|
||||||
let dataSourceDidUpdated = PassthroughSubject<Void, Never>()
|
let dataSourceDidUpdated = PassthroughSubject<Void, Never>()
|
||||||
|
@ -161,7 +161,7 @@ final class NotificationViewModel: NSObject {
|
||||||
|
|
||||||
extension NotificationViewModel {
|
extension NotificationViewModel {
|
||||||
enum NotificationSegment: Int {
|
enum NotificationSegment: Int {
|
||||||
case EveryThing
|
case everyThing
|
||||||
case Mentions
|
case mentions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,13 @@ extension WizardCardView {
|
||||||
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.minY), radius: radius, startAngle: -.pi / 2, endAngle: -.pi, clockwise: false)
|
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.minY), radius: radius, startAngle: -.pi / 2, endAngle: -.pi, clockwise: false)
|
||||||
path.addLine(to: CGPoint(x: rect.minX - radius, y: rect.maxY + radius + WizardCardView.bubbleArrowHeight))
|
path.addLine(to: CGPoint(x: rect.minX - radius, y: rect.maxY + radius + WizardCardView.bubbleArrowHeight))
|
||||||
path.close()
|
path.close()
|
||||||
|
case .allCorners: // no arrow
|
||||||
|
path.move(to: CGPoint(x: rect.maxX, y: rect.maxY + radius))
|
||||||
|
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.maxY), radius: radius, startAngle: .pi / 2, endAngle: .pi, clockwise: true)
|
||||||
|
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.minY), radius: radius, startAngle: .pi, endAngle: .pi / 2 * 3, clockwise: true)
|
||||||
|
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.minY), radius: radius, startAngle: .pi / 2 * 3, endAngle: .pi * 2, clockwise: true)
|
||||||
|
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius, startAngle: .pi * 2, endAngle: .pi / 2 * 5, clockwise: true)
|
||||||
|
path.close()
|
||||||
default:
|
default:
|
||||||
assertionFailure("FIXME")
|
assertionFailure("FIXME")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// FollowerListViewController+Provider.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import Combine
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
|
||||||
|
extension FollowerListViewController: UserProvider {
|
||||||
|
|
||||||
|
func mastodonUser() -> Future<MastodonUser?, Never> {
|
||||||
|
Future { promise in
|
||||||
|
promise(.success(nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mastodonUser(for cell: UITableViewCell?) -> Future<MastodonUser?, Never> {
|
||||||
|
Future { [weak self] promise in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let diffableDataSource = self.viewModel.diffableDataSource else {
|
||||||
|
assertionFailure()
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let cell = cell,
|
||||||
|
let indexPath = self.tableView.indexPath(for: cell),
|
||||||
|
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let managedObjectContext = self.viewModel.userFetchedResultsController.fetchedResultsController.managedObjectContext
|
||||||
|
|
||||||
|
switch item {
|
||||||
|
case .follower(let objectID),
|
||||||
|
.following(let objectID):
|
||||||
|
managedObjectContext.perform {
|
||||||
|
let user = managedObjectContext.object(with: objectID) as? MastodonUser
|
||||||
|
promise(.success(user))
|
||||||
|
}
|
||||||
|
case .bottomLoader, .bottomHeader:
|
||||||
|
promise(.success(nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
//
|
||||||
|
// FollowerListViewController.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import GameplayKit
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
final class FollowerListViewController: UIViewController, NeedsDependency {
|
||||||
|
|
||||||
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
||||||
|
var viewModel: FollowerListViewModel!
|
||||||
|
|
||||||
|
lazy var tableView: UITableView = {
|
||||||
|
let tableView = UITableView()
|
||||||
|
tableView.register(UserTableViewCell.self, forCellReuseIdentifier: String(describing: UserTableViewCell.self))
|
||||||
|
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
|
||||||
|
tableView.register(TimelineFooterTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineFooterTableViewCell.self))
|
||||||
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FollowerListViewController {
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor
|
||||||
|
ThemeService.shared.currentTheme
|
||||||
|
.receive(on: RunLoop.main)
|
||||||
|
.sink { [weak self] theme in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.view.backgroundColor = theme.secondarySystemBackgroundColor
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.addSubview(tableView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
tableView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||||
|
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
|
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
|
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
|
])
|
||||||
|
|
||||||
|
tableView.delegate = self
|
||||||
|
viewModel.setupDiffableDataSource(
|
||||||
|
for: tableView,
|
||||||
|
dependency: self
|
||||||
|
)
|
||||||
|
// TODO: add UserTableViewCellDelegate
|
||||||
|
|
||||||
|
// trigger user timeline loading
|
||||||
|
Publishers.CombineLatest(
|
||||||
|
viewModel.domain.removeDuplicates().eraseToAnyPublisher(),
|
||||||
|
viewModel.userID.removeDuplicates().eraseToAnyPublisher()
|
||||||
|
)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.viewModel.stateMachine.enter(FollowerListViewModel.State.Reloading.self)
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - LoadMoreConfigurableTableViewContainer
|
||||||
|
extension FollowerListViewController: LoadMoreConfigurableTableViewContainer {
|
||||||
|
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
|
||||||
|
typealias LoadingState = FollowerListViewModel.State.Loading
|
||||||
|
var loadMoreConfigurableTableView: UITableView { tableView }
|
||||||
|
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.stateMachine }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UIScrollViewDelegate
|
||||||
|
extension FollowerListViewController {
|
||||||
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
handleScrollViewDidScroll(scrollView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - UITableViewDelegate
|
||||||
|
extension FollowerListViewController: UITableViewDelegate {
|
||||||
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
handleTableView(tableView, didSelectRowAt: indexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UserTableViewCellDelegate
|
||||||
|
extension FollowerListViewController: UserTableViewCellDelegate { }
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// FollowerListViewModel+Diffable.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension FollowerListViewModel {
|
||||||
|
func setupDiffableDataSource(
|
||||||
|
for tableView: UITableView,
|
||||||
|
dependency: NeedsDependency
|
||||||
|
) {
|
||||||
|
diffableDataSource = UserSection.tableViewDiffableDataSource(
|
||||||
|
for: tableView,
|
||||||
|
dependency: dependency,
|
||||||
|
managedObjectContext: userFetchedResultsController.fetchedResultsController.managedObjectContext
|
||||||
|
)
|
||||||
|
|
||||||
|
// workaround to append loader wrong animation issue
|
||||||
|
// set empty section to make update animation top-to-bottom style
|
||||||
|
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
|
||||||
|
snapshot.appendSections([.main])
|
||||||
|
snapshot.appendItems([.bottomLoader], toSection: .main)
|
||||||
|
if #available(iOS 15.0, *) {
|
||||||
|
diffableDataSource?.applySnapshotUsingReloadData(snapshot, completion: nil)
|
||||||
|
} else {
|
||||||
|
// Fallback on earlier versions
|
||||||
|
diffableDataSource?.apply(snapshot, animatingDifferences: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
userFetchedResultsController.objectIDs
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] objectIDs in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let diffableDataSource = self.diffableDataSource else { return }
|
||||||
|
|
||||||
|
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
|
||||||
|
snapshot.appendSections([.main])
|
||||||
|
let items: [UserItem] = objectIDs.map {
|
||||||
|
UserItem.follower(objectID: $0)
|
||||||
|
}
|
||||||
|
snapshot.appendItems(items, toSection: .main)
|
||||||
|
|
||||||
|
if let currentState = self.stateMachine.currentState {
|
||||||
|
switch currentState {
|
||||||
|
case is State.Idle, is State.Loading, is State.Fail:
|
||||||
|
snapshot.appendItems([.bottomLoader], toSection: .main)
|
||||||
|
case is State.NoMore:
|
||||||
|
guard let activeMastodonAuthenticationBox = self.context.authenticationService.activeMastodonAuthenticationBox.value,
|
||||||
|
let userID = self.userID.value,
|
||||||
|
userID != activeMastodonAuthenticationBox.userID
|
||||||
|
else { break }
|
||||||
|
let text = L10n.Scene.Follower.footer
|
||||||
|
snapshot.appendItems([.bottomHeader(text: text)], toSection: .main)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diffableDataSource.apply(snapshot)
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
//
|
||||||
|
// FollowerListViewModel+State.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import Foundation
|
||||||
|
import GameplayKit
|
||||||
|
import MastodonSDK
|
||||||
|
|
||||||
|
extension FollowerListViewModel {
|
||||||
|
class State: GKState {
|
||||||
|
weak var viewModel: FollowerListViewModel?
|
||||||
|
|
||||||
|
init(viewModel: FollowerListViewModel) {
|
||||||
|
self.viewModel = viewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FollowerListViewModel.State {
|
||||||
|
class Initial: FollowerListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
guard let viewModel = viewModel else { return false }
|
||||||
|
switch stateClass {
|
||||||
|
case is Reloading.Type:
|
||||||
|
return viewModel.userID.value != nil
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Reloading: FollowerListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Loading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
|
||||||
|
|
||||||
|
// reset
|
||||||
|
viewModel.userFetchedResultsController.userIDs.value = []
|
||||||
|
|
||||||
|
stateMachine.enter(Loading.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fail: FollowerListViewModel.State {
|
||||||
|
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Loading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
guard let _ = viewModel, let stateMachine = stateMachine else { return }
|
||||||
|
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: retry loading 3s later…", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: retry loading", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
stateMachine.enter(Loading.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Idle: FollowerListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Reloading.Type, is Loading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Loading: FollowerListViewModel.State {
|
||||||
|
|
||||||
|
var maxID: String?
|
||||||
|
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Fail.Type:
|
||||||
|
return true
|
||||||
|
case is Idle.Type:
|
||||||
|
return true
|
||||||
|
case is NoMore.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
|
||||||
|
if previousState is Reloading {
|
||||||
|
maxID = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
|
||||||
|
|
||||||
|
guard let userID = viewModel.userID.value, !userID.isEmpty else {
|
||||||
|
stateMachine.enter(Fail.self)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let activeMastodonAuthenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else {
|
||||||
|
stateMachine.enter(Fail.self)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.context.apiService.followers(
|
||||||
|
userID: userID,
|
||||||
|
maxID: maxID,
|
||||||
|
authorizationBox: activeMastodonAuthenticationBox
|
||||||
|
)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { completion in
|
||||||
|
switch completion {
|
||||||
|
case .failure(let error):
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch user timeline fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||||
|
stateMachine.enter(Fail.self)
|
||||||
|
case .finished:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} receiveValue: { response in
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
|
||||||
|
var hasNewAppend = false
|
||||||
|
var userIDs = viewModel.userFetchedResultsController.userIDs.value
|
||||||
|
for user in response.value {
|
||||||
|
guard !userIDs.contains(user.id) else { continue }
|
||||||
|
userIDs.append(user.id)
|
||||||
|
hasNewAppend = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxID = response.link?.maxID
|
||||||
|
|
||||||
|
if hasNewAppend && maxID != nil {
|
||||||
|
stateMachine.enter(Idle.self)
|
||||||
|
} else {
|
||||||
|
stateMachine.enter(NoMore.self)
|
||||||
|
}
|
||||||
|
self.maxID = maxID
|
||||||
|
viewModel.userFetchedResultsController.userIDs.value = userIDs
|
||||||
|
}
|
||||||
|
.store(in: &viewModel.disposeBag)
|
||||||
|
} // end func didEnter
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoMore: FollowerListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Reloading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// FollowerListViewModel.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
import Combine
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
import GameplayKit
|
||||||
|
import MastodonSDK
|
||||||
|
|
||||||
|
final class FollowerListViewModel {
|
||||||
|
|
||||||
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
// input
|
||||||
|
let context: AppContext
|
||||||
|
let domain: CurrentValueSubject<String?, Never>
|
||||||
|
let userID: CurrentValueSubject<String?, Never>
|
||||||
|
let userFetchedResultsController: UserFetchedResultsController
|
||||||
|
|
||||||
|
// output
|
||||||
|
var diffableDataSource: UITableViewDiffableDataSource<UserSection, UserItem>?
|
||||||
|
private(set) lazy var stateMachine: GKStateMachine = {
|
||||||
|
let stateMachine = GKStateMachine(states: [
|
||||||
|
State.Initial(viewModel: self),
|
||||||
|
State.Reloading(viewModel: self),
|
||||||
|
State.Fail(viewModel: self),
|
||||||
|
State.Idle(viewModel: self),
|
||||||
|
State.Loading(viewModel: self),
|
||||||
|
State.NoMore(viewModel: self),
|
||||||
|
])
|
||||||
|
stateMachine.enter(State.Initial.self)
|
||||||
|
return stateMachine
|
||||||
|
}()
|
||||||
|
|
||||||
|
init(context: AppContext, domain: String?, userID: String?) {
|
||||||
|
self.context = context
|
||||||
|
self.userFetchedResultsController = UserFetchedResultsController(
|
||||||
|
managedObjectContext: context.managedObjectContext,
|
||||||
|
domain: domain,
|
||||||
|
additionalTweetPredicate: nil
|
||||||
|
)
|
||||||
|
self.domain = CurrentValueSubject(domain)
|
||||||
|
self.userID = CurrentValueSubject(userID)
|
||||||
|
// super.init()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// FollowingListViewController+Provider.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import Combine
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
|
||||||
|
extension FollowingListViewController: UserProvider {
|
||||||
|
|
||||||
|
func mastodonUser() -> Future<MastodonUser?, Never> {
|
||||||
|
Future { promise in
|
||||||
|
promise(.success(nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mastodonUser(for cell: UITableViewCell?) -> Future<MastodonUser?, Never> {
|
||||||
|
Future { [weak self] promise in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let diffableDataSource = self.viewModel.diffableDataSource else {
|
||||||
|
assertionFailure()
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let cell = cell,
|
||||||
|
let indexPath = self.tableView.indexPath(for: cell),
|
||||||
|
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let managedObjectContext = self.viewModel.userFetchedResultsController.fetchedResultsController.managedObjectContext
|
||||||
|
|
||||||
|
switch item {
|
||||||
|
case .follower(let objectID),
|
||||||
|
.following(let objectID):
|
||||||
|
managedObjectContext.perform {
|
||||||
|
let user = managedObjectContext.object(with: objectID) as? MastodonUser
|
||||||
|
promise(.success(user))
|
||||||
|
}
|
||||||
|
case .bottomLoader, .bottomHeader:
|
||||||
|
promise(.success(nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
//
|
||||||
|
// FollowingListViewController.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import UIKit
|
||||||
|
import GameplayKit
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
final class FollowingListViewController: UIViewController, NeedsDependency {
|
||||||
|
|
||||||
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
||||||
|
var viewModel: FollowingListViewModel!
|
||||||
|
|
||||||
|
lazy var tableView: UITableView = {
|
||||||
|
let tableView = UITableView()
|
||||||
|
tableView.register(UserTableViewCell.self, forCellReuseIdentifier: String(describing: UserTableViewCell.self))
|
||||||
|
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
|
||||||
|
tableView.register(TimelineFooterTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineFooterTableViewCell.self))
|
||||||
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FollowingListViewController {
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor
|
||||||
|
ThemeService.shared.currentTheme
|
||||||
|
.receive(on: RunLoop.main)
|
||||||
|
.sink { [weak self] theme in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.view.backgroundColor = theme.secondarySystemBackgroundColor
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.addSubview(tableView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
tableView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||||
|
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
|
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
|
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
|
])
|
||||||
|
|
||||||
|
tableView.delegate = self
|
||||||
|
viewModel.setupDiffableDataSource(
|
||||||
|
for: tableView,
|
||||||
|
dependency: self
|
||||||
|
)
|
||||||
|
// TODO: add UserTableViewCellDelegate
|
||||||
|
|
||||||
|
// trigger user timeline loading
|
||||||
|
Publishers.CombineLatest(
|
||||||
|
viewModel.domain.removeDuplicates().eraseToAnyPublisher(),
|
||||||
|
viewModel.userID.removeDuplicates().eraseToAnyPublisher()
|
||||||
|
)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.viewModel.stateMachine.enter(FollowingListViewModel.State.Reloading.self)
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - LoadMoreConfigurableTableViewContainer
|
||||||
|
extension FollowingListViewController: LoadMoreConfigurableTableViewContainer {
|
||||||
|
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
|
||||||
|
typealias LoadingState = FollowingListViewModel.State.Loading
|
||||||
|
var loadMoreConfigurableTableView: UITableView { tableView }
|
||||||
|
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.stateMachine }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UIScrollViewDelegate
|
||||||
|
extension FollowingListViewController {
|
||||||
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
handleScrollViewDidScroll(scrollView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - UITableViewDelegate
|
||||||
|
extension FollowingListViewController: UITableViewDelegate {
|
||||||
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
handleTableView(tableView, didSelectRowAt: indexPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UserTableViewCellDelegate
|
||||||
|
extension FollowingListViewController: UserTableViewCellDelegate { }
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// FollowingListViewModel+Diffable.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension FollowingListViewModel {
|
||||||
|
func setupDiffableDataSource(
|
||||||
|
for tableView: UITableView,
|
||||||
|
dependency: NeedsDependency
|
||||||
|
) {
|
||||||
|
diffableDataSource = UserSection.tableViewDiffableDataSource(
|
||||||
|
for: tableView,
|
||||||
|
dependency: dependency,
|
||||||
|
managedObjectContext: userFetchedResultsController.fetchedResultsController.managedObjectContext
|
||||||
|
)
|
||||||
|
|
||||||
|
// workaround to append loader wrong animation issue
|
||||||
|
// set empty section to make update animation top-to-bottom style
|
||||||
|
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
|
||||||
|
snapshot.appendSections([.main])
|
||||||
|
snapshot.appendItems([.bottomLoader], toSection: .main)
|
||||||
|
if #available(iOS 15.0, *) {
|
||||||
|
diffableDataSource?.applySnapshotUsingReloadData(snapshot, completion: nil)
|
||||||
|
} else {
|
||||||
|
// Fallback on earlier versions
|
||||||
|
diffableDataSource?.apply(snapshot, animatingDifferences: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
userFetchedResultsController.objectIDs
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] objectIDs in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let diffableDataSource = self.diffableDataSource else { return }
|
||||||
|
|
||||||
|
var snapshot = NSDiffableDataSourceSnapshot<UserSection, UserItem>()
|
||||||
|
snapshot.appendSections([.main])
|
||||||
|
let items: [UserItem] = objectIDs.map {
|
||||||
|
UserItem.following(objectID: $0)
|
||||||
|
}
|
||||||
|
snapshot.appendItems(items, toSection: .main)
|
||||||
|
|
||||||
|
if let currentState = self.stateMachine.currentState {
|
||||||
|
switch currentState {
|
||||||
|
case is State.Idle, is State.Loading, is State.Fail:
|
||||||
|
snapshot.appendItems([.bottomLoader], toSection: .main)
|
||||||
|
case is State.NoMore:
|
||||||
|
guard let activeMastodonAuthenticationBox = self.context.authenticationService.activeMastodonAuthenticationBox.value,
|
||||||
|
let userID = self.userID.value,
|
||||||
|
userID != activeMastodonAuthenticationBox.userID
|
||||||
|
else { break }
|
||||||
|
let text = L10n.Scene.Following.footer
|
||||||
|
snapshot.appendItems([.bottomHeader(text: text)], toSection: .main)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diffableDataSource.apply(snapshot)
|
||||||
|
}
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
//
|
||||||
|
// FollowingListViewModel+State.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
|
import Foundation
|
||||||
|
import GameplayKit
|
||||||
|
import MastodonSDK
|
||||||
|
|
||||||
|
extension FollowingListViewModel {
|
||||||
|
class State: GKState {
|
||||||
|
weak var viewModel: FollowingListViewModel?
|
||||||
|
|
||||||
|
init(viewModel: FollowingListViewModel) {
|
||||||
|
self.viewModel = viewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
os_log("%{public}s[%{public}ld], %{public}s: enter %s, previous: %s", ((#file as NSString).lastPathComponent), #line, #function, self.debugDescription, previousState.debugDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FollowingListViewModel.State {
|
||||||
|
class Initial: FollowingListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
guard let viewModel = viewModel else { return false }
|
||||||
|
switch stateClass {
|
||||||
|
case is Reloading.Type:
|
||||||
|
return viewModel.userID.value != nil
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Reloading: FollowingListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Loading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
|
||||||
|
|
||||||
|
// reset
|
||||||
|
viewModel.userFetchedResultsController.userIDs.value = []
|
||||||
|
|
||||||
|
stateMachine.enter(Loading.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fail: FollowingListViewModel.State {
|
||||||
|
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Loading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
guard let _ = viewModel, let stateMachine = stateMachine else { return }
|
||||||
|
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: retry loading 3s later…", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: retry loading", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
stateMachine.enter(Loading.self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Idle: FollowingListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Reloading.Type, is Loading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Loading: FollowingListViewModel.State {
|
||||||
|
|
||||||
|
var maxID: String?
|
||||||
|
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Fail.Type:
|
||||||
|
return true
|
||||||
|
case is Idle.Type:
|
||||||
|
return true
|
||||||
|
case is NoMore.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
|
||||||
|
if previousState is Reloading {
|
||||||
|
maxID = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
|
||||||
|
|
||||||
|
guard let userID = viewModel.userID.value, !userID.isEmpty else {
|
||||||
|
stateMachine.enter(Fail.self)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let activeMastodonAuthenticationBox = viewModel.context.authenticationService.activeMastodonAuthenticationBox.value else {
|
||||||
|
stateMachine.enter(Fail.self)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.context.apiService.following(
|
||||||
|
userID: userID,
|
||||||
|
maxID: maxID,
|
||||||
|
authorizationBox: activeMastodonAuthenticationBox
|
||||||
|
)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { completion in
|
||||||
|
switch completion {
|
||||||
|
case .failure(let error):
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch user timeline fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||||
|
stateMachine.enter(Fail.self)
|
||||||
|
case .finished:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} receiveValue: { response in
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
|
||||||
|
var hasNewAppend = false
|
||||||
|
var userIDs = viewModel.userFetchedResultsController.userIDs.value
|
||||||
|
for user in response.value {
|
||||||
|
guard !userIDs.contains(user.id) else { continue }
|
||||||
|
userIDs.append(user.id)
|
||||||
|
hasNewAppend = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxID = response.link?.maxID
|
||||||
|
|
||||||
|
if hasNewAppend, maxID != nil {
|
||||||
|
stateMachine.enter(Idle.self)
|
||||||
|
} else {
|
||||||
|
stateMachine.enter(NoMore.self)
|
||||||
|
}
|
||||||
|
self.maxID = maxID
|
||||||
|
viewModel.userFetchedResultsController.userIDs.value = userIDs
|
||||||
|
}
|
||||||
|
.store(in: &viewModel.disposeBag)
|
||||||
|
} // end func didEnter
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoMore: FollowingListViewModel.State {
|
||||||
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
|
switch stateClass {
|
||||||
|
case is Reloading.Type:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didEnter(from previousState: GKState?) {
|
||||||
|
super.didEnter(from: previousState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// FollowingListViewModel.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-11-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
import Combine
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
import GameplayKit
|
||||||
|
import MastodonSDK
|
||||||
|
|
||||||
|
final class FollowingListViewModel {
|
||||||
|
|
||||||
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
// input
|
||||||
|
let context: AppContext
|
||||||
|
let domain: CurrentValueSubject<String?, Never>
|
||||||
|
let userID: CurrentValueSubject<String?, Never>
|
||||||
|
let userFetchedResultsController: UserFetchedResultsController
|
||||||
|
|
||||||
|
// output
|
||||||
|
var diffableDataSource: UITableViewDiffableDataSource<UserSection, UserItem>?
|
||||||
|
private(set) lazy var stateMachine: GKStateMachine = {
|
||||||
|
let stateMachine = GKStateMachine(states: [
|
||||||
|
State.Initial(viewModel: self),
|
||||||
|
State.Reloading(viewModel: self),
|
||||||
|
State.Fail(viewModel: self),
|
||||||
|
State.Idle(viewModel: self),
|
||||||
|
State.Loading(viewModel: self),
|
||||||
|
State.NoMore(viewModel: self),
|
||||||
|
])
|
||||||
|
stateMachine.enter(State.Initial.self)
|
||||||
|
return stateMachine
|
||||||
|
}()
|
||||||
|
|
||||||
|
init(context: AppContext, domain: String?, userID: String?) {
|
||||||
|
self.context = context
|
||||||
|
self.userFetchedResultsController = UserFetchedResultsController(
|
||||||
|
managedObjectContext: context.managedObjectContext,
|
||||||
|
domain: domain,
|
||||||
|
additionalTweetPredicate: nil
|
||||||
|
)
|
||||||
|
self.domain = CurrentValueSubject(domain)
|
||||||
|
self.userID = CurrentValueSubject(userID)
|
||||||
|
// super.init()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,10 +44,11 @@ final class ProfileHeaderViewController: UIViewController {
|
||||||
|
|
||||||
let profileHeaderView = ProfileHeaderView()
|
let profileHeaderView = ProfileHeaderView()
|
||||||
let pageSegmentedControl: UISegmentedControl = {
|
let pageSegmentedControl: UISegmentedControl = {
|
||||||
let segmenetedControl = UISegmentedControl(items: ["A", "B"])
|
let segmentedControl = UISegmentedControl(items: ["A", "B"])
|
||||||
segmenetedControl.selectedSegmentIndex = 0
|
segmentedControl.selectedSegmentIndex = 0
|
||||||
return segmenetedControl
|
return segmentedControl
|
||||||
}()
|
}()
|
||||||
|
var pageSegmentedControlLeadingLayoutConstraint: NSLayoutConstraint!
|
||||||
|
|
||||||
private var isBannerPinned = false
|
private var isBannerPinned = false
|
||||||
private var bottomShadowAlpha: CGFloat = 0.0
|
private var bottomShadowAlpha: CGFloat = 0.0
|
||||||
|
@ -118,9 +119,10 @@ extension ProfileHeaderViewController {
|
||||||
|
|
||||||
pageSegmentedControl.translatesAutoresizingMaskIntoConstraints = false
|
pageSegmentedControl.translatesAutoresizingMaskIntoConstraints = false
|
||||||
view.addSubview(pageSegmentedControl)
|
view.addSubview(pageSegmentedControl)
|
||||||
|
pageSegmentedControlLeadingLayoutConstraint = pageSegmentedControl.leadingAnchor.constraint(equalTo: view.leadingAnchor)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
pageSegmentedControl.topAnchor.constraint(equalTo: profileHeaderView.bottomAnchor, constant: ProfileHeaderViewController.segmentedControlMarginHeight),
|
pageSegmentedControl.topAnchor.constraint(equalTo: profileHeaderView.bottomAnchor, constant: ProfileHeaderViewController.segmentedControlMarginHeight),
|
||||||
pageSegmentedControl.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor),
|
pageSegmentedControlLeadingLayoutConstraint, // Fix iPad layout issue
|
||||||
pageSegmentedControl.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor),
|
pageSegmentedControl.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor),
|
||||||
view.bottomAnchor.constraint(equalTo: pageSegmentedControl.bottomAnchor, constant: ProfileHeaderViewController.segmentedControlMarginHeight),
|
view.bottomAnchor.constraint(equalTo: pageSegmentedControl.bottomAnchor, constant: ProfileHeaderViewController.segmentedControlMarginHeight),
|
||||||
pageSegmentedControl.heightAnchor.constraint(equalToConstant: ProfileHeaderViewController.segmentedControlHeight).priority(.defaultHigh),
|
pageSegmentedControl.heightAnchor.constraint(equalToConstant: ProfileHeaderViewController.segmentedControlHeight).priority(.defaultHigh),
|
||||||
|
@ -133,10 +135,10 @@ extension ProfileHeaderViewController {
|
||||||
viewModel.isTitleViewContentOffsetSet.eraseToAnyPublisher()
|
viewModel.isTitleViewContentOffsetSet.eraseToAnyPublisher()
|
||||||
)
|
)
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] viewDidAppear, isTitleViewContentOffsetDidSetted in
|
.sink { [weak self] viewDidAppear, isTitleViewContentOffsetDidSet in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.titleView.titleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSetted ? 1 : 0
|
self.titleView.titleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSet ? 1 : 0
|
||||||
self.titleView.subtitleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSetted ? 1 : 0
|
self.titleView.subtitleLabel.alpha = viewDidAppear && isTitleViewContentOffsetDidSet ? 1 : 0
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
@ -283,6 +285,13 @@ extension ProfileHeaderViewController {
|
||||||
setupBottomShadow()
|
setupBottomShadow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewLayoutMarginsDidChange() {
|
||||||
|
super.viewLayoutMarginsDidChange()
|
||||||
|
|
||||||
|
let margin = view.frame.maxX - view.readableContentGuide.layoutFrame.maxX
|
||||||
|
pageSegmentedControlLeadingLayoutConstraint.constant = margin
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ProfileHeaderViewController {
|
extension ProfileHeaderViewController {
|
||||||
|
|
|
@ -17,9 +17,7 @@ protocol ProfileHeaderViewDelegate: AnyObject {
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, relationshipButtonDidPressed button: ProfileRelationshipActionButton)
|
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, relationshipButtonDidPressed button: ProfileRelationshipActionButton)
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, metaTextView: MetaTextView, metaDidPressed meta: Meta)
|
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, metaTextView: MetaTextView, metaDidPressed meta: Meta)
|
||||||
|
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView: ProfileStatusDashboardView, postDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView dashboardView: ProfileStatusDashboardView, dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView, meter: ProfileStatusDashboardView.Meter)
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView: ProfileStatusDashboardView, followingDashboardMeterViewDidPressed followingDashboardMeterView: ProfileStatusDashboardMeterView)
|
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView: ProfileStatusDashboardView, followersDashboardMeterViewDidPressed followersDashboardMeterView: ProfileStatusDashboardMeterView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ProfileHeaderView: UIView {
|
final class ProfileHeaderView: UIView {
|
||||||
|
@ -443,6 +441,7 @@ extension ProfileHeaderView {
|
||||||
bringSubviewToFront(bannerContainerView)
|
bringSubviewToFront(bannerContainerView)
|
||||||
bringSubviewToFront(nameContainerStackView)
|
bringSubviewToFront(nameContainerStackView)
|
||||||
|
|
||||||
|
statusDashboardView.delegate = self
|
||||||
bioMetaText.textView.delegate = self
|
bioMetaText.textView.delegate = self
|
||||||
bioMetaText.textView.linkDelegate = self
|
bioMetaText.textView.linkDelegate = self
|
||||||
|
|
||||||
|
@ -549,19 +548,9 @@ extension ProfileHeaderView: MetaTextViewDelegate {
|
||||||
|
|
||||||
// MARK: - ProfileStatusDashboardViewDelegate
|
// MARK: - ProfileStatusDashboardViewDelegate
|
||||||
extension ProfileHeaderView: ProfileStatusDashboardViewDelegate {
|
extension ProfileHeaderView: ProfileStatusDashboardViewDelegate {
|
||||||
|
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView, meter: ProfileStatusDashboardView.Meter) {
|
||||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, postDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView) {
|
delegate?.profileHeaderView(self, profileStatusDashboardView: dashboardView, dashboardMeterViewDidPressed: dashboardMeterView, meter: meter)
|
||||||
delegate?.profileHeaderView(self, profileStatusDashboardView: dashboardView, postDashboardMeterViewDidPressed: dashboardMeterView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, followingDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView) {
|
|
||||||
delegate?.profileHeaderView(self, profileStatusDashboardView: dashboardView, followingDashboardMeterViewDidPressed: dashboardMeterView)
|
|
||||||
}
|
|
||||||
|
|
||||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, followersDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView) {
|
|
||||||
delegate?.profileHeaderView(self, profileStatusDashboardView: dashboardView, followersDashboardMeterViewDidPressed: dashboardMeterView)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - AvatarConfigurableView
|
// MARK: - AvatarConfigurableView
|
||||||
|
|
|
@ -9,9 +9,7 @@ import os.log
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
protocol ProfileStatusDashboardViewDelegate: AnyObject {
|
protocol ProfileStatusDashboardViewDelegate: AnyObject {
|
||||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, postDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView, meter: ProfileStatusDashboardView.Meter)
|
||||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, followingDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
|
||||||
func profileStatusDashboardView(_ dashboardView: ProfileStatusDashboardView, followersDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ProfileStatusDashboardView: UIView {
|
final class ProfileStatusDashboardView: UIView {
|
||||||
|
@ -34,6 +32,14 @@ final class ProfileStatusDashboardView: UIView {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ProfileStatusDashboardView {
|
||||||
|
enum Meter: Hashable {
|
||||||
|
case post
|
||||||
|
case following
|
||||||
|
case follower
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension ProfileStatusDashboardView {
|
extension ProfileStatusDashboardView {
|
||||||
private func _init() {
|
private func _init() {
|
||||||
let containerStackView = UIStackView()
|
let containerStackView = UIStackView()
|
||||||
|
@ -67,7 +73,6 @@ extension ProfileStatusDashboardView {
|
||||||
tapGestureRecognizer.addTarget(self, action: #selector(ProfileStatusDashboardView.tapGestureRecognizerHandler(_:)))
|
tapGestureRecognizer.addTarget(self, action: #selector(ProfileStatusDashboardView.tapGestureRecognizerHandler(_:)))
|
||||||
meterView.addGestureRecognizer(tapGestureRecognizer)
|
meterView.addGestureRecognizer(tapGestureRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +83,15 @@ extension ProfileStatusDashboardView {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sourceView === postDashboardMeterView {
|
switch sourceView {
|
||||||
delegate?.profileStatusDashboardView(self, postDashboardMeterViewDidPressed: sourceView)
|
case postDashboardMeterView:
|
||||||
} else if sourceView === followingDashboardMeterView {
|
delegate?.profileStatusDashboardView(self, dashboardMeterViewDidPressed: sourceView, meter: .post)
|
||||||
delegate?.profileStatusDashboardView(self, followingDashboardMeterViewDidPressed: sourceView)
|
case followingDashboardMeterView:
|
||||||
} else if sourceView === followersDashboardMeterView {
|
delegate?.profileStatusDashboardView(self, dashboardMeterViewDidPressed: sourceView, meter: .following)
|
||||||
delegate?.profileStatusDashboardView(self, followersDashboardMeterViewDidPressed: sourceView)
|
case followersDashboardMeterView:
|
||||||
|
delegate?.profileStatusDashboardView(self, dashboardMeterViewDidPressed: sourceView, meter: .follower)
|
||||||
|
default:
|
||||||
|
assertionFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,6 +517,7 @@ extension ProfileViewController {
|
||||||
.assign(to: \.value, on: profileHeaderViewController.viewModel.displayProfileInfo.note)
|
.assign(to: \.value, on: profileHeaderViewController.viewModel.displayProfileInfo.note)
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
viewModel.statusesCount
|
viewModel.statusesCount
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] count in
|
.sink { [weak self] count in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"
|
let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"
|
||||||
|
@ -526,6 +527,7 @@ extension ProfileViewController {
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
viewModel.followingCount
|
viewModel.followingCount
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] count in
|
.sink { [weak self] count in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"
|
let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"
|
||||||
|
@ -535,6 +537,7 @@ extension ProfileViewController {
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
viewModel.followersCount
|
viewModel.followersCount
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] count in
|
.sink { [weak self] count in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"
|
let text = count.flatMap { MastodonMetricFormatter().string(from: $0) } ?? "-"
|
||||||
|
@ -766,7 +769,6 @@ extension ProfileViewController: ProfilePagingViewControllerDelegate {
|
||||||
|
|
||||||
// MARK: - ProfileHeaderViewDelegate
|
// MARK: - ProfileHeaderViewDelegate
|
||||||
extension ProfileViewController: ProfileHeaderViewDelegate {
|
extension ProfileViewController: ProfileHeaderViewDelegate {
|
||||||
|
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, avatarImageViewDidPressed imageView: UIImageView) {
|
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, avatarImageViewDidPressed imageView: UIImageView) {
|
||||||
guard let mastodonUser = viewModel.mastodonUser.value else { return }
|
guard let mastodonUser = viewModel.mastodonUser.value else { return }
|
||||||
guard let avatar = imageView.image else { return }
|
guard let avatar = imageView.image else { return }
|
||||||
|
@ -979,15 +981,40 @@ extension ProfileViewController: ProfileHeaderViewDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView: ProfileStatusDashboardView, postDashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView) {
|
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView dashboardView: ProfileStatusDashboardView, dashboardMeterViewDidPressed dashboardMeterView: ProfileStatusDashboardMeterView, meter: ProfileStatusDashboardView.Meter) {
|
||||||
|
switch meter {
|
||||||
}
|
case .post:
|
||||||
|
// do nothing
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView: ProfileStatusDashboardView, followingDashboardMeterViewDidPressed followingDashboardMeterView: ProfileStatusDashboardMeterView) {
|
break
|
||||||
|
case .follower:
|
||||||
}
|
guard let domain = viewModel.domain.value,
|
||||||
|
let userID = viewModel.userID.value
|
||||||
func profileHeaderView(_ profileHeaderView: ProfileHeaderView, profileStatusDashboardView: ProfileStatusDashboardView, followersDashboardMeterViewDidPressed followersDashboardMeterView: ProfileStatusDashboardMeterView) {
|
else { return }
|
||||||
|
let followerListViewModel = FollowerListViewModel(
|
||||||
|
context: context,
|
||||||
|
domain: domain,
|
||||||
|
userID: userID
|
||||||
|
)
|
||||||
|
coordinator.present(
|
||||||
|
scene: .follower(viewModel: followerListViewModel),
|
||||||
|
from: self,
|
||||||
|
transition: .show
|
||||||
|
)
|
||||||
|
case .following:
|
||||||
|
guard let domain = viewModel.domain.value,
|
||||||
|
let userID = viewModel.userID.value
|
||||||
|
else { return }
|
||||||
|
let followingListViewModel = FollowingListViewModel(
|
||||||
|
context: context,
|
||||||
|
domain: domain,
|
||||||
|
userID: userID
|
||||||
|
)
|
||||||
|
coordinator.present(
|
||||||
|
scene: .following(viewModel: followingListViewModel),
|
||||||
|
from: self,
|
||||||
|
transition: .show
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import Combine
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
import GameplayKit
|
import GameplayKit
|
||||||
|
|
||||||
// TODO: adopt MediaPreviewableViewController
|
|
||||||
final class UserTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
final class UserTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||||
|
|
||||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
|
@ -251,7 +251,7 @@ class ReportViewController: UIViewController, NeedsDependency {
|
||||||
= UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel,
|
= UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.cancel,
|
||||||
target: self,
|
target: self,
|
||||||
action: #selector(doneButtonDidClick))
|
action: #selector(doneButtonDidClick))
|
||||||
navigationItem.rightBarButtonItem?.tintColor = Asset.Colors.brandBlue.color
|
navigationItem.rightBarButtonItem?.tintColor = ThemeService.tintColor
|
||||||
|
|
||||||
// fetch old mastodon user
|
// fetch old mastodon user
|
||||||
let beReportedUser: MastodonUser? = {
|
let beReportedUser: MastodonUser? = {
|
||||||
|
|
|
@ -10,6 +10,10 @@ import UIKit
|
||||||
import Combine
|
import Combine
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
|
|
||||||
|
protocol ContentSplitViewControllerDelegate: AnyObject {
|
||||||
|
func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab)
|
||||||
|
}
|
||||||
|
|
||||||
final class ContentSplitViewController: UIViewController, NeedsDependency {
|
final class ContentSplitViewController: UIViewController, NeedsDependency {
|
||||||
|
|
||||||
var disposeBag = Set<AnyCancellable>()
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
@ -19,6 +23,8 @@ final class ContentSplitViewController: UIViewController, NeedsDependency {
|
||||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
|
||||||
|
weak var delegate: ContentSplitViewControllerDelegate?
|
||||||
|
|
||||||
private(set) lazy var sidebarViewController: SidebarViewController = {
|
private(set) lazy var sidebarViewController: SidebarViewController = {
|
||||||
let sidebarViewController = SidebarViewController()
|
let sidebarViewController = SidebarViewController()
|
||||||
sidebarViewController.context = context
|
sidebarViewController.context = context
|
||||||
|
@ -31,6 +37,10 @@ final class ContentSplitViewController: UIViewController, NeedsDependency {
|
||||||
@Published var currentSupplementaryTab: MainTabBarController.Tab = .home
|
@Published var currentSupplementaryTab: MainTabBarController.Tab = .home
|
||||||
private(set) lazy var mainTabBarController: MainTabBarController = {
|
private(set) lazy var mainTabBarController: MainTabBarController = {
|
||||||
let mainTabBarController = MainTabBarController(context: context, coordinator: coordinator)
|
let mainTabBarController = MainTabBarController(context: context, coordinator: coordinator)
|
||||||
|
if let homeTimelineViewController = mainTabBarController.viewController(of: HomeTimelineViewController.self) {
|
||||||
|
homeTimelineViewController.viewModel.displayComposeBarButtonItem.value = false
|
||||||
|
homeTimelineViewController.viewModel.displaySettingBarButtonItem.value = false
|
||||||
|
}
|
||||||
return mainTabBarController
|
return mainTabBarController
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -47,7 +57,7 @@ extension ContentSplitViewController {
|
||||||
navigationController?.setNavigationBarHidden(true, animated: false)
|
navigationController?.setNavigationBarHidden(true, animated: false)
|
||||||
|
|
||||||
addChild(sidebarViewController)
|
addChild(sidebarViewController)
|
||||||
sidebarViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
sidebarViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
view.addSubview(sidebarViewController.view)
|
view.addSubview(sidebarViewController.view)
|
||||||
sidebarViewController.didMove(toParent: self)
|
sidebarViewController.didMove(toParent: self)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
@ -63,7 +73,7 @@ extension ContentSplitViewController {
|
||||||
sidebarViewController.didMove(toParent: self)
|
sidebarViewController.didMove(toParent: self)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
mainTabBarController.view.topAnchor.constraint(equalTo: view.topAnchor),
|
mainTabBarController.view.topAnchor.constraint(equalTo: view.topAnchor),
|
||||||
mainTabBarController.view.leadingAnchor.constraint(equalTo: sidebarViewController.view.trailingAnchor),
|
mainTabBarController.view.leadingAnchor.constraint(equalTo: sidebarViewController.view.trailingAnchor, constant: UIView.separatorLineHeight(of: view)),
|
||||||
mainTabBarController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
mainTabBarController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
mainTabBarController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
mainTabBarController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
])
|
])
|
||||||
|
@ -83,10 +93,16 @@ extension ContentSplitViewController {
|
||||||
extension ContentSplitViewController: SidebarViewControllerDelegate {
|
extension ContentSplitViewController: SidebarViewControllerDelegate {
|
||||||
|
|
||||||
func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab) {
|
func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab) {
|
||||||
guard let _ = MainTabBarController.Tab.allCases.firstIndex(of: tab) else {
|
delegate?.contentSplitViewController(self, sidebarViewController: sidebarViewController, didSelectTab: tab)
|
||||||
assertionFailure()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
currentSupplementaryTab = tab
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sidebarViewController(_ sidebarViewController: SidebarViewController, didLongPressItem item: SidebarViewModel.Item, sourceView: UIView) {
|
||||||
|
guard case let .tab(tab) = item, tab == .me else { return }
|
||||||
|
|
||||||
|
let accountListViewController = coordinator.present(scene: .accountList, from: nil, transition: .popover(sourceView: sourceView)) as! AccountListViewController
|
||||||
|
accountListViewController.dragIndicatorView.barView.isHidden = true
|
||||||
|
// content width needs > 300 to make checkmark display
|
||||||
|
accountListViewController.preferredContentSize = CGSize(width: 375, height: 400)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue