From 90a24445e3e076890fb2078a1f429139776fc9da Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 29 Oct 2021 21:45:10 +0200 Subject: [PATCH 01/87] New translations app.json (Kurmanji (Kurdish)) --- .../StringsConvertor/input/kmr_TR/app.json | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index 9798c86c2..5330ea480 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -111,7 +111,7 @@ "open_author_profile": "Profîla nivîskaran veke", "open_reblogger_profile": "Profîla nivîskaran veke", "reply_status": "Bersivê bide şandiyê", - "toggle_reblog": "Toggle Reblog on Post", + "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ê" @@ -294,7 +294,7 @@ }, "confirm_email": { "title": "Tiştekî dawî.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "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" @@ -305,8 +305,8 @@ "resend_email": "E-namyê yê dîsa bişîne" }, "open_email_app": { - "title": "Check your inbox.", - "description": "We just sent you an email. Check your junk folder if you haven’t.", + "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" } @@ -334,15 +334,15 @@ "photo_library": "Wênegeh", "browse": "Bigere" }, - "content_input_placeholder": "Type or paste what’s on your mind", + "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": "Describe the photo for the visually-impaired...", - "description_video": "Describe the video for the visually-impaired..." + "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", @@ -355,7 +355,7 @@ "option_number": "Vebijêrk %ld" }, "content_warning": { - "placeholder": "Write an accurate warning here..." + "placeholder": "Li vir hişyariyek hûrgilî binivîsine..." }, "visibility": { "public": "Gelemperî", @@ -364,14 +364,14 @@ "direct": "Tenê mirovên ku min qalkirî" }, "auto_complete": { - "space_to_add": "Space to add" + "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": "Custom Emoji Picker", - "enable_content_warning": "Enable Content Warning", + "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ê" }, @@ -467,7 +467,7 @@ }, "thread": { "back_title": "Şandî", - "title": "Post from %s" + "title": "Şandî ji %s" }, "settings": { "title": "Sazkarî", @@ -482,7 +482,7 @@ "title": "Agahdarî", "favorites": "Şandiyên min hez kir", "follows": "Min şopand", - "boosts": "Reblogs my post", + "boosts": "Şandiya min ji nû ve binivîsine", "mentions": "Qale min kir", "trigger": { "anyone": "her kes", @@ -494,39 +494,39 @@ }, "preference": { "title": "Hilbijarte", - "true_black_dark_mode": "True black dark mode", - "disable_avatar_animation": "Disable animated avatars", - "disable_emoji_animation": "Disable animated emojis", - "using_default_browser": "Use default browser to open links" + "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": "The Boring Zone", - "account_settings": "Account Settings", - "terms": "Terms of Service", - "privacy": "Privacy Policy" + "title": "Devera acizker", + "account_settings": "Sazkariyên ajimêr", + "terms": "Mercên bikaranînê", + "privacy": "Polîtikaya nihêniyê" }, "spicy_zone": { - "title": "The Spicy Zone", - "clear": "Clear Media Cache", - "signout": "Sign Out" + "title": "Devera germ", + "clear": "Pêşbîra medyayê pak bike", + "signout": "Derkeve" } }, "footer": { - "mastodon_description": "Mastodon is open source software. You can report issues on GitHub at %s (%s)" + "mastodon_description": "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di %s (%s) de" }, "keyboard": { - "close_settings_window": "Close Settings Window" + "close_settings_window": "Sazkariyên çarçoveyê bigire" } }, "report": { "title": "%s ragihîne", "step1": "Gav 1 ji 2", "step2": "Gav 2 ji 2", - "content1": "Are there any other posts you’d like to add to the report?", - "content2": "Is there anything the moderators should know about this report?", + "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": "Type or paste additional comments" + "text_placeholder": "Şiroveyên daxwazkirê binivîsine an jî pê ve bike" }, "preview": { "keyboard": { @@ -537,13 +537,13 @@ }, "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": "Dismiss Account Switcher", + "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": "Double tap to dismiss this wizard" + "accessibility_hint": "Du caran bitikîne da ku çarçoveyahilpekok ji holê rakî" } } } \ No newline at end of file From 061ed1b4b197614b4efb15db5ebd7f5d62b9c959 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 29 Oct 2021 21:45:11 +0200 Subject: [PATCH 02/87] New translations Localizable.stringsdict (Kurmanji (Kurdish)) --- .../StringsConvertor/input/kmr_TR/Localizable.stringsdict | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Localization/StringsConvertor/input/kmr_TR/Localizable.stringsdict b/Localization/StringsConvertor/input/kmr_TR/Localizable.stringsdict index 064b8bf2b..8ae1b812a 100644 --- a/Localization/StringsConvertor/input/kmr_TR/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/kmr_TR/Localizable.stringsdict @@ -109,9 +109,9 @@ NSStringFormatValueTypeKey ld one - 1 reblog + 1 ji nû ve nivîsandin other - %ld reblogs + %ld ji nû ve nivîsandin plural.count.vote From 4f531a72d12369e0ebfc66f41d574641916156b9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:12 +0100 Subject: [PATCH 03/87] New translations app.json (Kurmanji (Kurdish)) --- Localization/StringsConvertor/input/kmr_TR/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index 5330ea480..4fdfd0e7d 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -67,6 +67,7 @@ "done": "Qediya", "confirm": "Bipejirîne", "continue": "Bidomîne", + "compose": "Compose", "cancel": "Dev jê berde", "discard": "Biavêje", "try_again": "Dîsa biceribîne", @@ -413,6 +414,12 @@ } } }, + "follower": { + "footer": "Followers from other servers are not displayed." + }, + "following": { + "footer": "Follows from other servers are not displayed." + }, "search": { "title": "Bigere", "search_bar": { From 9ffa6a2e6717f0887a4fe8ba0e8da8acb180cfce Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:13 +0100 Subject: [PATCH 04/87] New translations app.json (Russian) --- Localization/StringsConvertor/input/ru_RU/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/ru_RU/app.json b/Localization/StringsConvertor/input/ru_RU/app.json index a5c34023a..c1ad3ee49 100644 --- a/Localization/StringsConvertor/input/ru_RU/app.json +++ b/Localization/StringsConvertor/input/ru_RU/app.json @@ -67,6 +67,7 @@ "done": "Готово", "confirm": "Подтвердить", "continue": "Продолжить", + "compose": "Compose", "cancel": "Отмена", "discard": "Отмена", "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": { "title": "Поиск", "search_bar": { From 9d265d9a18a091394ca43f2659df2fa78009d656 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:14 +0100 Subject: [PATCH 05/87] New translations app.json (Welsh) --- Localization/StringsConvertor/input/cy_GB/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/cy_GB/app.json b/Localization/StringsConvertor/input/cy_GB/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/cy_GB/app.json +++ b/Localization/StringsConvertor/input/cy_GB/app.json @@ -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": { "title": "Search", "search_bar": { From 88909303360557a3f9908ddfe418a65e70568c66 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:15 +0100 Subject: [PATCH 06/87] New translations app.json (Hindi) --- Localization/StringsConvertor/input/hi_IN/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/hi_IN/app.json b/Localization/StringsConvertor/input/hi_IN/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/hi_IN/app.json +++ b/Localization/StringsConvertor/input/hi_IN/app.json @@ -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": { "title": "Search", "search_bar": { From ede66ab8575014376d52c93e6a97e978b1292e35 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:16 +0100 Subject: [PATCH 07/87] New translations app.json (Thai) --- Localization/StringsConvertor/input/th_TH/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/th_TH/app.json b/Localization/StringsConvertor/input/th_TH/app.json index fb3024f2b..f9e56214c 100644 --- a/Localization/StringsConvertor/input/th_TH/app.json +++ b/Localization/StringsConvertor/input/th_TH/app.json @@ -67,6 +67,7 @@ "done": "เสร็จสิ้น", "confirm": "ยืนยัน", "continue": "ดำเนินการต่อ", + "compose": "Compose", "cancel": "ยกเลิก", "discard": "ละทิ้ง", "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": { "title": "ค้นหา", "search_bar": { From bf556d6e674c135ba291cfba35fb5894932d81c7 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:17 +0100 Subject: [PATCH 08/87] New translations app.json (Spanish, Argentina) --- Localization/StringsConvertor/input/es_AR/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/es_AR/app.json b/Localization/StringsConvertor/input/es_AR/app.json index 4ae708521..c0c884e24 100644 --- a/Localization/StringsConvertor/input/es_AR/app.json +++ b/Localization/StringsConvertor/input/es_AR/app.json @@ -67,6 +67,7 @@ "done": "Listo", "confirm": "Confirmar", "continue": "Continuar", + "compose": "Compose", "cancel": "Cancelar", "discard": "Descartar", "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": { "title": "Buscar", "search_bar": { From 9644a2332925756799601122b0643632151d3903 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:18 +0100 Subject: [PATCH 09/87] New translations app.json (Indonesian) --- Localization/StringsConvertor/input/id_ID/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/id_ID/app.json b/Localization/StringsConvertor/input/id_ID/app.json index 6ba29ad8f..6f3171254 100644 --- a/Localization/StringsConvertor/input/id_ID/app.json +++ b/Localization/StringsConvertor/input/id_ID/app.json @@ -67,6 +67,7 @@ "done": "Selesai", "confirm": "Konfirmasi", "continue": "Lanjut", + "compose": "Compose", "cancel": "Batal", "discard": "Discard", "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": { "title": "Cari", "search_bar": { From f983162838b7cc16cebe44529da3f521fb3f2d36 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:19 +0100 Subject: [PATCH 10/87] New translations app.json (Portuguese, Brazilian) --- Localization/StringsConvertor/input/pt_BR/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/pt_BR/app.json b/Localization/StringsConvertor/input/pt_BR/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/pt_BR/app.json +++ b/Localization/StringsConvertor/input/pt_BR/app.json @@ -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": { "title": "Search", "search_bar": { From 157721384630e73ecbcebd18ce1107da9c905f85 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:20 +0100 Subject: [PATCH 11/87] New translations app.json (English) --- Localization/StringsConvertor/input/en_US/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/en_US/app.json b/Localization/StringsConvertor/input/en_US/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/en_US/app.json +++ b/Localization/StringsConvertor/input/en_US/app.json @@ -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": { "title": "Search", "search_bar": { From 78e0b170d0713d79ceb146caf85b2aad87af617e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:21 +0100 Subject: [PATCH 12/87] New translations app.json (Chinese Traditional) --- Localization/StringsConvertor/input/zh_TW/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/zh_TW/app.json b/Localization/StringsConvertor/input/zh_TW/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/zh_TW/app.json +++ b/Localization/StringsConvertor/input/zh_TW/app.json @@ -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": { "title": "Search", "search_bar": { From 5fca21c7d9e3f262b11a44946c282c519f3b90d9 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:22 +0100 Subject: [PATCH 13/87] New translations app.json (Chinese Simplified) --- Localization/StringsConvertor/input/zh_CN/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/zh_CN/app.json b/Localization/StringsConvertor/input/zh_CN/app.json index b7728b60c..b3a8866bb 100644 --- a/Localization/StringsConvertor/input/zh_CN/app.json +++ b/Localization/StringsConvertor/input/zh_CN/app.json @@ -67,6 +67,7 @@ "done": "完成", "confirm": "确认", "continue": "继续", + "compose": "Compose", "cancel": "取消", "discard": "放弃", "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": { "title": "搜索", "search_bar": { From 627c2b4999f039aa9b07094ee47ff923ac44c5ed Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:23 +0100 Subject: [PATCH 14/87] New translations app.json (Swedish) --- Localization/StringsConvertor/input/sv_SE/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/sv_SE/app.json b/Localization/StringsConvertor/input/sv_SE/app.json index d0a9ad795..7acf48755 100644 --- a/Localization/StringsConvertor/input/sv_SE/app.json +++ b/Localization/StringsConvertor/input/sv_SE/app.json @@ -67,6 +67,7 @@ "done": "Done", "confirm": "Confirm", "continue": "Fortsätt", + "compose": "Compose", "cancel": "Avbryt", "discard": "Discard", "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": { "title": "Search", "search_bar": { From 05ec22990e0632fa3345582ab9b6463635391407 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:24 +0100 Subject: [PATCH 15/87] New translations app.json (Portuguese) --- Localization/StringsConvertor/input/pt_PT/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/pt_PT/app.json b/Localization/StringsConvertor/input/pt_PT/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/pt_PT/app.json +++ b/Localization/StringsConvertor/input/pt_PT/app.json @@ -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": { "title": "Search", "search_bar": { From b85bfb65d3d418de32763737b63870daa840ad75 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:25 +0100 Subject: [PATCH 16/87] New translations app.json (Japanese) --- Localization/StringsConvertor/input/ja_JP/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/ja_JP/app.json b/Localization/StringsConvertor/input/ja_JP/app.json index 1c7d408f5..417ca3e3a 100644 --- a/Localization/StringsConvertor/input/ja_JP/app.json +++ b/Localization/StringsConvertor/input/ja_JP/app.json @@ -67,6 +67,7 @@ "done": "完了", "confirm": "確認", "continue": "続ける", + "compose": "Compose", "cancel": "キャンセル", "discard": "破棄", "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": { "title": "検索", "search_bar": { From e4eada46f4d48c658d0013ae0f3f1cbd3de5fa54 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:26 +0100 Subject: [PATCH 17/87] New translations app.json (Dutch) --- Localization/StringsConvertor/input/nl_NL/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/nl_NL/app.json b/Localization/StringsConvertor/input/nl_NL/app.json index d57a38ef2..d8ee1e574 100644 --- a/Localization/StringsConvertor/input/nl_NL/app.json +++ b/Localization/StringsConvertor/input/nl_NL/app.json @@ -67,6 +67,7 @@ "done": "Klaar", "confirm": "Bevestigen", "continue": "Doorgaan", + "compose": "Compose", "cancel": "Annuleren", "discard": "Weggooien", "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": { "title": "Zoeken", "search_bar": { From 12c8198cb943ade95ca3897905da903b26f637e4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:27 +0100 Subject: [PATCH 18/87] New translations app.json (Korean) --- Localization/StringsConvertor/input/ko_KR/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/ko_KR/app.json b/Localization/StringsConvertor/input/ko_KR/app.json index a9fb71ee8..571b14659 100644 --- a/Localization/StringsConvertor/input/ko_KR/app.json +++ b/Localization/StringsConvertor/input/ko_KR/app.json @@ -67,6 +67,7 @@ "done": "완료", "confirm": "확인", "continue": "계속", + "compose": "Compose", "cancel": "취소", "discard": "버리기", "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": { "title": "검색", "search_bar": { From 54cfcc10aaaa40717203bdbfe02f80fd1a94d03e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:28 +0100 Subject: [PATCH 19/87] New translations app.json (Danish) --- Localization/StringsConvertor/input/da_DK/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/da_DK/app.json b/Localization/StringsConvertor/input/da_DK/app.json index 3ec77cf10..5c01ae7e0 100644 --- a/Localization/StringsConvertor/input/da_DK/app.json +++ b/Localization/StringsConvertor/input/da_DK/app.json @@ -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": { "title": "Search", "search_bar": { From 5a5e9f60f77039e21aa7ee7b973a981e5d819a4c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:30 +0100 Subject: [PATCH 20/87] New translations app.json (Catalan) --- Localization/StringsConvertor/input/ca_ES/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/ca_ES/app.json b/Localization/StringsConvertor/input/ca_ES/app.json index 9ffdc5bee..41349483e 100644 --- a/Localization/StringsConvertor/input/ca_ES/app.json +++ b/Localization/StringsConvertor/input/ca_ES/app.json @@ -67,6 +67,7 @@ "done": "Fet", "confirm": "Confirma", "continue": "Continua", + "compose": "Compose", "cancel": "Cancel·la", "discard": "Descarta", "try_again": "Torna a provar", @@ -413,6 +414,12 @@ } } }, + "follower": { + "footer": "Followers from other servers are not displayed." + }, + "following": { + "footer": "Follows from other servers are not displayed." + }, "search": { "title": "Cerca", "search_bar": { From 0ed72e48be1ad9868ea6255bb8b7f5b8deb17ef4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:31 +0100 Subject: [PATCH 21/87] New translations app.json (Spanish) --- Localization/StringsConvertor/input/es_ES/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/es_ES/app.json b/Localization/StringsConvertor/input/es_ES/app.json index 5e96daff0..1710318b9 100644 --- a/Localization/StringsConvertor/input/es_ES/app.json +++ b/Localization/StringsConvertor/input/es_ES/app.json @@ -67,6 +67,7 @@ "done": "Hecho", "confirm": "Confirmar", "continue": "Continuar", + "compose": "Compose", "cancel": "Cancelar", "discard": "Descartar", "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": { "title": "Buscar", "search_bar": { From a310737ee3720321b0274828d154c37ad40e0fb4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:32 +0100 Subject: [PATCH 22/87] New translations app.json (French) --- Localization/StringsConvertor/input/fr_FR/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/fr_FR/app.json b/Localization/StringsConvertor/input/fr_FR/app.json index 5c101dbe9..e27f097e4 100644 --- a/Localization/StringsConvertor/input/fr_FR/app.json +++ b/Localization/StringsConvertor/input/fr_FR/app.json @@ -67,6 +67,7 @@ "done": "Terminé", "confirm": "Confirmer", "continue": "Continuer", + "compose": "Compose", "cancel": "Annuler", "discard": "Abandonner", "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": { "title": "Rechercher", "search_bar": { From 894d62ba231a69251a91941d769edf2d66f86dde Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:33 +0100 Subject: [PATCH 23/87] New translations app.json (Romanian) --- Localization/StringsConvertor/input/ro_RO/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/ro_RO/app.json b/Localization/StringsConvertor/input/ro_RO/app.json index ef819f8e6..3927247ee 100644 --- a/Localization/StringsConvertor/input/ro_RO/app.json +++ b/Localization/StringsConvertor/input/ro_RO/app.json @@ -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": { "title": "Search", "search_bar": { From 2b70a770cf1aa63b784ef06fc7a939f1c62758d0 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:34 +0100 Subject: [PATCH 24/87] New translations app.json (Scottish Gaelic) --- Localization/StringsConvertor/input/gd_GB/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/gd_GB/app.json b/Localization/StringsConvertor/input/gd_GB/app.json index a73925bba..12d862a55 100644 --- a/Localization/StringsConvertor/input/gd_GB/app.json +++ b/Localization/StringsConvertor/input/gd_GB/app.json @@ -67,6 +67,7 @@ "done": "Deiseil", "confirm": "Dearbh", "continue": "Lean air adhart", + "compose": "Compose", "cancel": "Sguir dheth", "discard": "Tilg air falbh", "try_again": "Feuch ris a-rithist", @@ -413,6 +414,12 @@ } } }, + "follower": { + "footer": "Followers from other servers are not displayed." + }, + "following": { + "footer": "Follows from other servers are not displayed." + }, "search": { "title": "Lorg", "search_bar": { From 5c0a07110c827fcf7fb4109f86e6cd67c683fbcd Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:35 +0100 Subject: [PATCH 25/87] New translations app.json (Arabic) --- Localization/StringsConvertor/input/ar_SA/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/ar_SA/app.json b/Localization/StringsConvertor/input/ar_SA/app.json index 4bf55d918..44aebc154 100644 --- a/Localization/StringsConvertor/input/ar_SA/app.json +++ b/Localization/StringsConvertor/input/ar_SA/app.json @@ -67,6 +67,7 @@ "done": "تمّ", "confirm": "تأكيد", "continue": "واصل", + "compose": "Compose", "cancel": "إلغاء", "discard": "تجاهل", "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": { "title": "بحث", "search_bar": { From caadcf8eaa7ab3ec2335a5c04702c13ead2555bb Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:36 +0100 Subject: [PATCH 26/87] New translations app.json (German) --- Localization/StringsConvertor/input/de_DE/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/de_DE/app.json b/Localization/StringsConvertor/input/de_DE/app.json index 43d8ed70a..dc8cdf8c0 100644 --- a/Localization/StringsConvertor/input/de_DE/app.json +++ b/Localization/StringsConvertor/input/de_DE/app.json @@ -67,6 +67,7 @@ "done": "Fertig", "confirm": "Bestätigen", "continue": "Fortfahren", + "compose": "Compose", "cancel": "Abbrechen", "discard": "Verwerfen", "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": { "title": "Suche", "search_bar": { From 8ef001e02c999d3daedeeef88952a7987533e79c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 13:44:37 +0100 Subject: [PATCH 27/87] New translations app.json (Swedish, Finland) --- Localization/StringsConvertor/input/sv_FI/app.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Localization/StringsConvertor/input/sv_FI/app.json b/Localization/StringsConvertor/input/sv_FI/app.json index d0a9ad795..7acf48755 100644 --- a/Localization/StringsConvertor/input/sv_FI/app.json +++ b/Localization/StringsConvertor/input/sv_FI/app.json @@ -67,6 +67,7 @@ "done": "Done", "confirm": "Confirm", "continue": "Fortsätt", + "compose": "Compose", "cancel": "Avbryt", "discard": "Discard", "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": { "title": "Search", "search_bar": { From 3f945a1cf8839f016d9173026a4e659c00a4c6bf Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 14:40:30 +0100 Subject: [PATCH 28/87] New translations app.json (Kurmanji (Kurdish)) --- Localization/StringsConvertor/input/kmr_TR/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index 4fdfd0e7d..7534aede0 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -67,7 +67,7 @@ "done": "Qediya", "confirm": "Bipejirîne", "continue": "Bidomîne", - "compose": "Compose", + "compose": "Binivîsîne", "cancel": "Dev jê berde", "discard": "Biavêje", "try_again": "Dîsa biceribîne", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "Şopîner ji rajekerên din nayê dîtin." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "Şopandin ji rajekerên din nayê dîtin." }, "search": { "title": "Bigere", From a487c19cba3c9121e64579a4b87f8df738cd81d0 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 14:40:32 +0100 Subject: [PATCH 29/87] New translations app.json (Scottish Gaelic) --- Localization/StringsConvertor/input/gd_GB/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/gd_GB/app.json b/Localization/StringsConvertor/input/gd_GB/app.json index 12d862a55..b5c66f8f6 100644 --- a/Localization/StringsConvertor/input/gd_GB/app.json +++ b/Localization/StringsConvertor/input/gd_GB/app.json @@ -67,7 +67,7 @@ "done": "Deiseil", "confirm": "Dearbh", "continue": "Lean air adhart", - "compose": "Compose", + "compose": "Sgrìobh", "cancel": "Sguir dheth", "discard": "Tilg air falbh", "try_again": "Feuch ris a-rithist", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "Cha dèid luchd-leantainn o fhrithealaichean eile a shealltainn." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "Cha dèid cò air a leanas tu air frithealaichean eile a shealltainn." }, "search": { "title": "Lorg", From 45ee6941ba3f95515589f484e790a57834d44d69 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 14:40:33 +0100 Subject: [PATCH 30/87] New translations app.json (Catalan) --- Localization/StringsConvertor/input/ca_ES/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/ca_ES/app.json b/Localization/StringsConvertor/input/ca_ES/app.json index 41349483e..2ecd587c6 100644 --- a/Localization/StringsConvertor/input/ca_ES/app.json +++ b/Localization/StringsConvertor/input/ca_ES/app.json @@ -67,7 +67,7 @@ "done": "Fet", "confirm": "Confirma", "continue": "Continua", - "compose": "Compose", + "compose": "Composa", "cancel": "Cancel·la", "discard": "Descarta", "try_again": "Torna a provar", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "Els seguidors d'altres servidors no son mostrats." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "Els seguits d'altres servidors no son mostrats." }, "search": { "title": "Cerca", From 524f7c0cf6d4834f8136e8ca7a95b3e1fab050fb Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 1 Nov 2021 18:14:37 +0100 Subject: [PATCH 31/87] New translations Intents.stringsdict (Dutch) --- .../Intents/input/nl_NL/Intents.stringsdict | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Localization/StringsConvertor/Intents/input/nl_NL/Intents.stringsdict b/Localization/StringsConvertor/Intents/input/nl_NL/Intents.stringsdict index 18422c772..9043720db 100644 --- a/Localization/StringsConvertor/Intents/input/nl_NL/Intents.stringsdict +++ b/Localization/StringsConvertor/Intents/input/nl_NL/Intents.stringsdict @@ -5,7 +5,7 @@ There are ${count} options matching ‘${content}’. - 2 NSStringLocalizedFormatKey - There are %#@count_option@ matching ‘${content}’. + Er zijn %#@count_option@ die overeenkomen met ‘${content}’. count_option NSStringFormatSpecTypeKey @@ -13,7 +13,7 @@ NSStringFormatValueTypeKey %ld one - 1 option + 1 optie other %ld options @@ -21,7 +21,7 @@ There are ${count} options matching ‘${visibility}’. NSStringLocalizedFormatKey - There are %#@count_option@ matching ‘${visibility}’. + Er zijn %#@count_option@ die overeenkomen met ‘${visibility}’. count_option NSStringFormatSpecTypeKey @@ -29,7 +29,7 @@ NSStringFormatValueTypeKey %ld one - 1 option + 1 optie other %ld options From 0d39d061a1ee2be1a9f535d41372001c1324bfee Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 14:28:21 +0800 Subject: [PATCH 32/87] feat: update the notification tab "Mentions" segment table UI --- .../Diffiable/Item/NotificationItem.swift | 8 +- .../Section/Status/NotificationSection.swift | 296 ++++++++++-------- ...icationViewController+StatusProvider.swift | 17 +- .../NotificationViewController.swift | 134 +++++--- .../NotificationViewModel+Diffable.swift | 26 +- ...otificationViewModel+LoadOldestState.swift | 4 +- .../Notification/NotificationViewModel.swift | 8 +- .../Scene/Share/View/Content/StatusView.swift | 10 + 8 files changed, 319 insertions(+), 184 deletions(-) diff --git a/Mastodon/Diffiable/Item/NotificationItem.swift b/Mastodon/Diffiable/Item/NotificationItem.swift index 22949b3a5..fc7d0e0d9 100644 --- a/Mastodon/Diffiable/Item/NotificationItem.swift +++ b/Mastodon/Diffiable/Item/NotificationItem.swift @@ -10,7 +10,7 @@ import Foundation enum NotificationItem { case notification(objectID: NSManagedObjectID, attribute: Item.StatusAttribute) - + case notificationStatus(objectID: NSManagedObjectID, attribute: Item.StatusAttribute) // display notification status without card wrapper case bottomLoader } @@ -19,6 +19,8 @@ extension NotificationItem: Equatable { switch (lhs, rhs) { case (.notification(let idLeft, _), .notification(let idRight, _)): return idLeft == idRight + case (.notificationStatus(let idLeft, _), .notificationStatus(let idRight, _)): + return idLeft == idRight case (.bottomLoader, .bottomLoader): return true default: @@ -32,6 +34,8 @@ extension NotificationItem: Hashable { switch self { case .notification(let id, _): hasher.combine(id) + case .notificationStatus(let id, _): + hasher.combine(id) case .bottomLoader: hasher.combine(String(describing: NotificationItem.bottomLoader.self)) } @@ -43,6 +47,8 @@ extension NotificationItem { switch self { case .notification(let objectID, _): return .mastodonNotification(objectID: objectID) + case .notificationStatus(let objectID, _): + return .mastodonNotification(objectID: objectID) case .bottomLoader: return nil } diff --git a/Mastodon/Diffiable/Section/Status/NotificationSection.swift b/Mastodon/Diffiable/Section/Status/NotificationSection.swift index 215ba67cb..22283a479 100644 --- a/Mastodon/Diffiable/Section/Status/NotificationSection.swift +++ b/Mastodon/Diffiable/Section/Status/NotificationSection.swift @@ -21,9 +21,10 @@ enum NotificationSection: Equatable, Hashable { extension NotificationSection { static func tableViewDiffableDataSource( for tableView: UITableView, + dependency: NeedsDependency, managedObjectContext: NSManagedObjectContext, delegate: NotificationTableViewCellDelegate, - dependency: NeedsDependency + statusTableViewCellDelegate: StatusTableViewCellDelegate ) -> UITableViewDiffableDataSource { UITableViewDiffableDataSource(tableView: tableView) { [weak delegate, weak dependency] @@ -32,137 +33,45 @@ extension NotificationSection { switch notificationItem { case .notification(let objectID, let attribute): guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification, - !notification.isDeleted else { - return UITableViewCell() - } + !notification.isDeleted + else { return UITableViewCell() } let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationStatusTableViewCell.self), for: indexPath) as! NotificationStatusTableViewCell - cell.delegate = delegate - - // configure author - cell.configure( - with: AvatarConfigurableViewConfiguration( - avatarImageURL: notification.account.avatarImageURL() - ) + configure( + tableView: tableView, + cell: cell, + notification: notification, + dependency: dependency, + attribute: attribute ) + cell.delegate = delegate + return cell - 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)) - } + case .notificationStatus(objectID: let objectID, attribute: let attribute): + guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification, + !notification.isDeleted, + let status = notification.status, + let requestUserID = dependency.context.authenticationService.activeMastodonAuthenticationBox.value?.userID + else { return UITableViewCell() } + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell - 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 - } - + // configure cell + StatusSection.configureStatusTableViewCell( + cell: cell, + tableView: tableView, + timelineContext: .notifications, + dependency: dependency, + readableLayoutFrame: tableView.readableContentGuide.layoutFrame, + status: status, + requestUserID: requestUserID, + statusItemAttribute: attribute + ) + cell.statusView.headerContainerView.isHidden = true // set header hide + cell.statusView.actionToolbarContainer.isHidden = true // set toolbar hide + cell.statusView.actionToolbarPlaceholderPaddingView.isHidden = false + cell.delegate = statusTableViewCellDelegate + cell.isAccessibilityElement = true + StatusSection.configureStatusAccessibilityLabel(cell: cell) return cell 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 + } + } +} diff --git a/Mastodon/Scene/Notification/NotificationViewController+StatusProvider.swift b/Mastodon/Scene/Notification/NotificationViewController+StatusProvider.swift index 127cca1b9..57272404e 100644 --- a/Mastodon/Scene/Notification/NotificationViewController+StatusProvider.swift +++ b/Mastodon/Scene/Notification/NotificationViewController+StatusProvider.swift @@ -19,21 +19,25 @@ extension NotificationViewController: StatusProvider { func status(for cell: UITableViewCell?, indexPath: IndexPath?) -> Future { return Future { promise in - guard let cell = cell, - let diffableDataSource = self.viewModel.diffableDataSource, - let indexPath = self.tableView.indexPath(for: cell), + guard let diffableDataSource = self.viewModel.diffableDataSource else { + assertionFailure() + promise(.success(nil)) + return + } + guard let indexPath = indexPath ?? cell.flatMap({ self.tableView.indexPath(for: $0) }), let item = diffableDataSource.itemIdentifier(for: indexPath) else { promise(.success(nil)) return } switch item { - case .notification(let objectID, _): + case .notification(let objectID, _), + .notificationStatus(let objectID, _): self.viewModel.fetchedResultsController.managedObjectContext.perform { let notification = self.viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! MastodonNotification promise(.success(notification.status)) } - default: + case .bottomLoader: promise(.success(nil)) } } @@ -68,3 +72,6 @@ extension NotificationViewController: StatusProvider { } } + +// MARK: - UserProvider +extension NotificationViewController: UserProvider { } diff --git a/Mastodon/Scene/Notification/NotificationViewController.swift b/Mastodon/Scene/Notification/NotificationViewController.swift index 55b4504dc..0567d04dd 100644 --- a/Mastodon/Scene/Notification/NotificationViewController.swift +++ b/Mastodon/Scene/Notification/NotificationViewController.swift @@ -14,8 +14,10 @@ import OSLog import UIKit import Meta import MetaTextKit +import AVKit -final class NotificationViewController: UIViewController, NeedsDependency { +final class NotificationViewController: UIViewController, NeedsDependency, MediaPreviewableViewController { + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } @@ -23,15 +25,18 @@ final class NotificationViewController: UIViewController, NeedsDependency { var observations = Set() private(set) lazy var viewModel = NotificationViewModel(context: context) + + let mediaPreviewTransitionController = MediaPreviewTransitionController() let segmentControl: UISegmentedControl = { 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 }() let tableView: UITableView = { let tableView = ControlContainableTableView() + tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self)) tableView.register(NotificationStatusTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationStatusTableViewCell.self)) tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) tableView.estimatedRowHeight = UITableView.automaticDimension @@ -82,7 +87,12 @@ extension NotificationViewController { tableView.delegate = self viewModel.tableView = tableView viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self - viewModel.setupDiffableDataSource(for: tableView, delegate: self, dependency: self) + viewModel.setupDiffableDataSource( + for: tableView, + dependency: self, + delegate: self, + statusTableViewCellDelegate: self + ) viewModel.viewDidLoad.send() // bind refresh control @@ -128,9 +138,9 @@ extension NotificationViewController { self.viewModel.needsScrollToTopAfterDataSourceUpdate = true switch segment { - case .EveryThing: + case .everyThing: 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) } } @@ -148,8 +158,8 @@ extension NotificationViewController { override func viewWillAppear(_ animated: Bool) { 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 if tableView.contentOffset.y < view.frame.height * 0.5 { @@ -181,6 +191,12 @@ extension NotificationViewController { // reset notification count context.notificationService.clearNotificationCountForActiveUser() } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + aspectViewDidDisappear(animated) + } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) @@ -208,33 +224,34 @@ extension NotificationViewController { } } -// MARK: - StatusTableViewControllerAspect -extension NotificationViewController: StatusTableViewControllerAspect { } - -extension NotificationViewController { - +// MARK: - TableViewCellHeightCacheableContainer +extension NotificationViewController: TableViewCellHeightCacheableContainer { + var cellFrameCache: NSCache { return viewModel.cellFrameCache } + func cacheTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { guard let diffableDataSource = viewModel.diffableDataSource else { return } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } 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 } - let key = object.id as NSString + let key = object.objectID.hashValue let frame = cell.frame - viewModel.cellFrameCache.setObject(NSValue(cgRect: frame), forKey: key) + viewModel.cellFrameCache.setObject(NSValue(cgRect: frame), forKey: NSNumber(value: key)) case .bottomLoader: break } } - + func handleTableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { guard let diffableDataSource = viewModel.diffableDataSource else { return UITableView.automaticDimension } guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return UITableView.automaticDimension } 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 } - let key = object.id as NSString - guard let frame = viewModel.cellFrameCache.object(forKey: key)?.cgRectValue else { return UITableView.automaticDimension } + let key = object.objectID.hashValue + guard let frame = viewModel.cellFrameCache.object(forKey: NSNumber(value: key))?.cgRectValue else { return UITableView.automaticDimension } return frame.height case .bottomLoader: return TimelineLoaderTableViewCell.cellHeight @@ -242,22 +259,55 @@ extension NotificationViewController { } } + +// MARK: - StatusTableViewControllerAspect +extension NotificationViewController: StatusTableViewControllerAspect { } + // MARK: - 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 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) { - 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 { - return handleTableView(tableView, estimatedHeightForRowAt: indexPath) + func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { + 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 } } - - 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 @@ -388,6 +425,7 @@ extension NotificationViewController: ScrollViewContainer { } } +// MARK: - LoadMoreConfigurableTableViewContainer extension NotificationViewController: LoadMoreConfigurableTableViewContainer { typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell typealias LoadingState = NotificationViewModel.LoadOldestState.Loading @@ -395,6 +433,24 @@ extension NotificationViewController: LoadMoreConfigurableTableViewContainer { 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 { enum CategorySwitch: String, CaseIterable { @@ -452,9 +508,9 @@ extension NotificationViewController { switch category { case .showEverything: - viewModel.selectedIndex.value = .EveryThing + viewModel.selectedIndex.value = .everyThing case .showMentions: - viewModel.selectedIndex.value = .Mentions + viewModel.selectedIndex.value = .mentions } } diff --git a/Mastodon/Scene/Notification/NotificationViewModel+Diffable.swift b/Mastodon/Scene/Notification/NotificationViewModel+Diffable.swift index 6a542bf2c..6c7a70e43 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel+Diffable.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel+Diffable.swift @@ -14,14 +14,16 @@ import MastodonSDK extension NotificationViewModel { func setupDiffableDataSource( for tableView: UITableView, + dependency: NeedsDependency, delegate: NotificationTableViewCellDelegate, - dependency: NeedsDependency + statusTableViewCellDelegate: StatusTableViewCellDelegate ) { diffableDataSource = NotificationSection.tableViewDiffableDataSource( for: tableView, + dependency: dependency, managedObjectContext: fetchedResultsController.managedObjectContext, delegate: delegate, - dependency: dependency + statusTableViewCellDelegate: statusTableViewCellDelegate ) var snapshot = NSDiffableDataSourceSnapshot() @@ -81,11 +83,23 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate { } var newSnapshot = NSDiffableDataSourceSnapshot() newSnapshot.appendSections([.main]) - let items: [NotificationItem] = notifications.map { notification in - let attribute: Item.StatusAttribute = oldSnapshotAttributeDict[notification.objectID] ?? Item.StatusAttribute() - return NotificationItem.notification(objectID: notification.objectID, attribute: attribute) + + let segment = self.selectedIndex.value + 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 { newSnapshot.appendItems([.bottomLoader], toSection: .main) } diff --git a/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift b/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift index 9567d6cbb..bf2c03174 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel+LoadOldestState.swift @@ -92,13 +92,13 @@ extension NotificationViewModel.LoadOldestState { } receiveValue: { [weak viewModel] response in guard let viewModel = viewModel else { return } switch viewModel.selectedIndex.value { - case .EveryThing: + case .everyThing: if response.value.isEmpty { stateMachine.enter(NoMore.self) } else { stateMachine.enter(Idle.self) } - case .Mentions: + case .mentions: viewModel.noMoreNotification.value = response.value.isEmpty let list = response.value.filter { $0.type == Mastodon.Entity.Notification.NotificationType.mention } if list.isEmpty { diff --git a/Mastodon/Scene/Notification/NotificationViewModel.swift b/Mastodon/Scene/Notification/NotificationViewModel.swift index 712380917..98b7deec3 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel.swift @@ -23,13 +23,13 @@ final class NotificationViewModel: NSObject { weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate? let viewDidLoad = PassthroughSubject() - let selectedIndex = CurrentValueSubject(.EveryThing) + let selectedIndex = CurrentValueSubject(.everyThing) let noMoreNotification = CurrentValueSubject(false) let activeMastodonAuthenticationBox: CurrentValueSubject let fetchedResultsController: NSFetchedResultsController! let notificationPredicate = CurrentValueSubject(nil) - let cellFrameCache = NSCache() + let cellFrameCache = NSCache() var needsScrollToTopAfterDataSourceUpdate = false let dataSourceDidUpdated = PassthroughSubject() @@ -161,7 +161,7 @@ final class NotificationViewModel: NSObject { extension NotificationViewModel { enum NotificationSegment: Int { - case EveryThing - case Mentions + case everyThing + case mentions } } diff --git a/Mastodon/Scene/Share/View/Content/StatusView.swift b/Mastodon/Scene/Share/View/Content/StatusView.swift index 957764fa7..62eb3d6b0 100644 --- a/Mastodon/Scene/Share/View/Content/StatusView.swift +++ b/Mastodon/Scene/Share/View/Content/StatusView.swift @@ -203,6 +203,9 @@ final class StatusView: UIView { return actionToolbarContainer }() + // set display when needs bottom padding + let actionToolbarPlaceholderPaddingView = UIView() + let contentMetaText: MetaText = { let metaText = MetaText() metaText.textView.backgroundColor = .clear @@ -451,6 +454,13 @@ extension StatusView { containerStackView.sendSubviewToBack(actionToolbarContainer) actionToolbarContainer.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) actionToolbarContainer.setContentHuggingPriority(.required - 1, for: .vertical) + + actionToolbarPlaceholderPaddingView.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(actionToolbarPlaceholderPaddingView) + NSLayoutConstraint.activate([ + actionToolbarPlaceholderPaddingView.heightAnchor.constraint(equalToConstant: 12).priority(.required - 1), + ]) + actionToolbarPlaceholderPaddingView.isHidden = true headerContainerView.isHidden = true statusMosaicImageViewContainer.isHidden = true From 8ebb2e5347460b6a112992411cdad4d76f0a4f3d Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 14:56:42 +0800 Subject: [PATCH 33/87] feat: add following list --- Mastodon.xcodeproj/project.pbxproj | 28 +++ .../xcschemes/xcschememanagement.plist | 8 +- Mastodon/Coordinator/SceneCoordinator.swift | 5 + Mastodon/Diffiable/Item/UserItem.swift | 1 + Mastodon/Diffiable/Section/UserSection.swift | 3 +- .../FollowerListViewController+Provider.swift | 3 +- .../Follower/FollowerListViewController.swift | 7 +- .../FollowerListViewModel+Diffable.swift | 16 +- .../FollowerListViewModel+State.swift | 12 -- ...FollowingListViewController+Provider.swift | 51 +++++ .../FollowingListViewController.swift | 108 ++++++++++ .../FollowingListViewModel+Diffable.swift | 61 ++++++ .../FollowingListViewModel+State.swift | 196 ++++++++++++++++++ .../Following/FollowingListViewModel.swift | 53 +++++ .../Scene/Profile/ProfileViewController.swift | 15 +- 15 files changed, 536 insertions(+), 31 deletions(-) create mode 100644 Mastodon/Scene/Profile/Following/FollowingListViewController+Provider.swift create mode 100644 Mastodon/Scene/Profile/Following/FollowingListViewController.swift create mode 100644 Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift create mode 100644 Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift create mode 100644 Mastodon/Scene/Profile/Following/FollowingListViewModel.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 60f0f5d74..8408f3ac3 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -296,6 +296,11 @@ DB59F10425EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F10325EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.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 */; }; + 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 */; }; DB6180E02639194B0018D199 /* MediaPreviewPagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180DF2639194B0018D199 /* MediaPreviewPagingViewController.swift */; }; DB6180E326391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180E226391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift */; }; @@ -1110,6 +1115,11 @@ DB59F10325EF5EBC001F1DAB /* TableViewCellHeightCacheableContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewCellHeightCacheableContainer.swift; sourceTree = ""; }; DB59F10D25EF724F001F1DAB /* APIService+Poll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Poll.swift"; sourceTree = ""; }; DB59F11725EFA35B001F1DAB /* StripProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StripProgressView.swift; sourceTree = ""; }; + DB5B7294273112B100081888 /* FollowingListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingListViewController.swift; sourceTree = ""; }; + DB5B7297273112C800081888 /* FollowingListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingListViewModel.swift; sourceTree = ""; }; + DB5B72992731137900081888 /* FollowingListViewController+Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowingListViewController+Provider.swift"; sourceTree = ""; }; + DB5B729B273113C200081888 /* FollowingListViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowingListViewModel+Diffable.swift"; sourceTree = ""; }; + DB5B729D273113F300081888 /* FollowingListViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowingListViewModel+State.swift"; sourceTree = ""; }; DB6180DC263918E30018D199 /* MediaPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewController.swift; sourceTree = ""; }; DB6180DF2639194B0018D199 /* MediaPreviewPagingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewPagingViewController.swift; sourceTree = ""; }; DB6180E226391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerAnimatedTransitioning.swift; sourceTree = ""; }; @@ -2453,6 +2463,18 @@ path = View; sourceTree = ""; }; + 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 = ""; + }; DB6180DE263919350018D199 /* MediaPreview */ = { isa = PBXGroup; children = ( @@ -2902,6 +2924,7 @@ DBB5253B2611ECF5002F1F29 /* Timeline */, DBE3CDF1261C6B3100430CC6 /* Favorite */, DB6B74F0272FB55400C70B6E /* Follower */, + DB5B7296273112B400081888 /* Following */, DB9D6BFE25E4F5940051B173 /* ProfileViewController.swift */, DBAE3F812615DDA3004B8251 /* ProfileViewController+UserProvider.swift */, DBB5255D2611F07A002F1F29 /* ProfileViewModel.swift */, @@ -3918,6 +3941,7 @@ DBAE3F8E2616E0B1004B8251 /* APIService+Block.swift in Sources */, 5DF1057F25F88A4100D6C0D4 /* TouchBlockingView.swift in Sources */, DB1D843426579931000346B3 /* TableViewControllerNavigateable.swift in Sources */, + DB5B729A2731137900081888 /* FollowingListViewController+Provider.swift in Sources */, 0FAA0FDF25E0B57E0017CCDE /* WelcomeViewController.swift in Sources */, 2D206B8C25F6015000143C56 /* AudioPlaybackService.swift in Sources */, 2D59819B25E4A581000FB903 /* MastodonConfirmEmailViewController.swift in Sources */, @@ -3929,6 +3953,7 @@ DB03A793272A7E5700EE37C5 /* SidebarListHeaderView.swift in Sources */, DB4FFC2B269EC39600D62E92 /* SearchToSearchDetailViewControllerAnimatedTransitioning.swift in Sources */, DBCC3B9526157E6E0045B23D /* APIService+Relationship.swift in Sources */, + DB5B7298273112C800081888 /* FollowingListViewModel.swift in Sources */, 2D7631B325C159F700929FB9 /* Item.swift in Sources */, 5DF1054125F886D400D6C0D4 /* VideoPlaybackService.swift in Sources */, DB6B35182601FA3400DC1E11 /* MastodonAttachmentService.swift in Sources */, @@ -4065,6 +4090,7 @@ DBE3CE01261D623D00430CC6 /* FavoriteViewModel+State.swift in Sources */, 2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */, 2D38F1EB25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift in Sources */, + DB5B7295273112B100081888 /* FollowingListViewController.swift in Sources */, 0F202201261326E6000C64BF /* HashtagTimelineViewModel.swift in Sources */, DB6D9F9726367249008423CD /* SettingsViewController.swift in Sources */, DB4F097F26A03DA600D62E92 /* SearchHistoryFetchedResultController.swift in Sources */, @@ -4075,8 +4101,10 @@ DB73BF47271199CA00781945 /* Instance.swift in Sources */, DB0F8150264D1E2500F2A12B /* PickServerLoaderTableViewCell.swift in Sources */, DB98337F25C9452D00AD9700 /* APIService+APIError.swift in Sources */, + DB5B729C273113C200081888 /* FollowingListViewModel+Diffable.swift in Sources */, DB9E0D6F25EE008500CFDD76 /* UIInterpolatingMotionEffect.swift in Sources */, DBB9759C262462E1004620BD /* ThreadMetaView.swift in Sources */, + DB5B729E273113F300081888 /* FollowingListViewModel+State.swift in Sources */, 2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */, 5DDDF1A92617489F00311060 /* Mastodon+Entity+History.swift in Sources */, DB59F11825EFA35B001F1DAB /* StripProgressView.swift in Sources */, diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index cb88c3960..2d2dd1932 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 42 + 36 CoreDataStack.xcscheme_^#shared#^_ orderHint - 43 + 35 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -97,7 +97,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 44 + 38 MastodonIntents.xcscheme_^#shared#^_ @@ -117,7 +117,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 41 + 37 SuppressBuildableAutocreation diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index cda20255b..e7611056f 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -179,6 +179,7 @@ extension SceneCoordinator { case profile(viewModel: ProfileViewModel) case favorite(viewModel: FavoriteViewModel) case follower(viewModel: FollowerListViewModel) + case following(viewModel: FollowingListViewModel) // setting case settings(viewModel: SettingsViewModel) @@ -429,6 +430,10 @@ private extension SceneCoordinator { let _viewController = FollowerListViewController() _viewController.viewModel = viewModel viewController = _viewController + case .following(let viewModel): + let _viewController = FollowingListViewController() + _viewController.viewModel = viewModel + viewController = _viewController case .suggestionAccount(let viewModel): let _viewController = SuggestionAccountViewController() _viewController.viewModel = viewModel diff --git a/Mastodon/Diffiable/Item/UserItem.swift b/Mastodon/Diffiable/Item/UserItem.swift index 6f3c591b1..bd15f35ea 100644 --- a/Mastodon/Diffiable/Item/UserItem.swift +++ b/Mastodon/Diffiable/Item/UserItem.swift @@ -10,6 +10,7 @@ import CoreData enum UserItem: Hashable { case follower(objectID: NSManagedObjectID) + case following(objectID: NSManagedObjectID) case bottomLoader case bottomHeader(text: String) } diff --git a/Mastodon/Diffiable/Section/UserSection.swift b/Mastodon/Diffiable/Section/UserSection.swift index 58e80c6e3..9c7e2f212 100644 --- a/Mastodon/Diffiable/Section/UserSection.swift +++ b/Mastodon/Diffiable/Section/UserSection.swift @@ -30,7 +30,8 @@ extension UserSection { ] tableView, indexPath, item -> UITableViewCell? in guard let dependency = dependency else { return UITableViewCell() } switch item { - case .follower(let objectID): + 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 diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewController+Provider.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewController+Provider.swift index 627ed7772..25e102846 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewController+Provider.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewController+Provider.swift @@ -37,7 +37,8 @@ extension FollowerListViewController: UserProvider { let managedObjectContext = self.viewModel.userFetchedResultsController.fetchedResultsController.managedObjectContext switch item { - case .follower(let objectID): + case .follower(let objectID), + .following(let objectID): managedObjectContext.perform { let user = managedObjectContext.object(with: objectID) as? MastodonUser promise(.success(user)) diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewController.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewController.swift index 428448666..97e62ea8d 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewController.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewController.swift @@ -7,11 +7,10 @@ import os.log import UIKit -import AVKit import GameplayKit import Combine -final class FollowerListViewController: UIViewController, NeedsDependency, MediaPreviewableViewController { +final class FollowerListViewController: UIViewController, NeedsDependency { var disposeBag = Set() @@ -19,9 +18,7 @@ final class FollowerListViewController: UIViewController, NeedsDependency, Media weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } var viewModel: FollowerListViewModel! - - let mediaPreviewTransitionController = MediaPreviewTransitionController() - + lazy var tableView: UITableView = { let tableView = UITableView() tableView.register(UserTableViewCell.self, forCellReuseIdentifier: String(describing: UserTableViewCell.self)) diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift index 90b9cb311..c048e1723 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift @@ -18,16 +18,19 @@ extension FollowerListViewModel { 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() snapshot.appendSections([.main]) - diffableDataSource?.apply(snapshot) - - // workaround to append loader wrong animation issue snapshot.appendItems([.bottomLoader], toSection: .main) - diffableDataSource?.apply(snapshot) + if #available(iOS 15.0, *) { + diffableDataSource?.applySnapshotUsingReloadData(snapshot, completion: nil) + } else { + // Fallback on earlier versions + diffableDataSource?.apply(snapshot, animatingDifferences: false) + } - userFetchedResultsController.objectIDs.removeDuplicates() + userFetchedResultsController.objectIDs .receive(on: DispatchQueue.main) .sink { [weak self] objectIDs in guard let self = self else { return } @@ -45,7 +48,8 @@ extension FollowerListViewModel { case is State.Idle, is State.Loading, is State.Fail: snapshot.appendItems([.bottomLoader], toSection: .main) case is State.NoMore: - break + let text = "Followers from other servers are not displayed." + snapshot.appendItems([.bottomHeader(text: text)], toSection: .main) default: break } diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift index b012a59bb..876933181 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift @@ -179,18 +179,6 @@ extension FollowerListViewModel.State { override func didEnter(from previousState: GKState?) { super.didEnter(from: previousState) - guard let viewModel = viewModel, let _ = stateMachine else { return } - guard let diffableDataSource = viewModel.diffableDataSource else { - assertionFailure() - return - } - DispatchQueue.main.async { - var snapshot = diffableDataSource.snapshot() - snapshot.deleteItems([.bottomLoader]) - let header = UserItem.bottomHeader(text: "Followers from other servers are not displayed") - snapshot.appendItems([header], toSection: .main) - diffableDataSource.apply(snapshot, animatingDifferences: false) - } } } } diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewController+Provider.swift b/Mastodon/Scene/Profile/Following/FollowingListViewController+Provider.swift new file mode 100644 index 000000000..aaeb52328 --- /dev/null +++ b/Mastodon/Scene/Profile/Following/FollowingListViewController+Provider.swift @@ -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 { + Future { promise in + promise(.success(nil)) + } + } + + func mastodonUser(for cell: UITableViewCell?) -> Future { + 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)) + } + } + } +} diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewController.swift b/Mastodon/Scene/Profile/Following/FollowingListViewController.swift new file mode 100644 index 000000000..35691b82d --- /dev/null +++ b/Mastodon/Scene/Profile/Following/FollowingListViewController.swift @@ -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() + + 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 { } diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift new file mode 100644 index 000000000..58af276d0 --- /dev/null +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift @@ -0,0 +1,61 @@ +// +// 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() + 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() + 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: + break + default: + break + } + } + + diffableDataSource.apply(snapshot) + } + .store(in: &disposeBag) + } +} diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift new file mode 100644 index 000000000..d5c30b43a --- /dev/null +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift @@ -0,0 +1,196 @@ +// +// 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.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: 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) + guard let viewModel = viewModel, let _ = stateMachine else { return } + guard let diffableDataSource = viewModel.diffableDataSource else { + assertionFailure() + return + } + DispatchQueue.main.async { + var snapshot = diffableDataSource.snapshot() + snapshot.deleteItems([.bottomLoader]) + let header = UserItem.bottomHeader(text: "Followers from other servers are not displayed") + snapshot.appendItems([header], toSection: .main) + diffableDataSource.apply(snapshot, animatingDifferences: false) + } + } + } +} diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift new file mode 100644 index 000000000..0677f6cb4 --- /dev/null +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift @@ -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() + + // input + let context: AppContext + let domain: CurrentValueSubject + let userID: CurrentValueSubject + let userFetchedResultsController: UserFetchedResultsController + + // output + var diffableDataSource: UITableViewDiffableDataSource? + 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() + + } +} diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 04d582315..5ff71ba99 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -1001,8 +1001,19 @@ extension ProfileViewController: ProfileHeaderViewDelegate { transition: .show ) case .following: - // TODO: - break + 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 + ) } } From 613916e0406d9c8a4823d089382e3f8b34e7bebf Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 2 Nov 2021 08:05:08 +0100 Subject: [PATCH 34/87] New translations app.json (Chinese Simplified) --- Localization/StringsConvertor/input/zh_CN/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/zh_CN/app.json b/Localization/StringsConvertor/input/zh_CN/app.json index b3a8866bb..905afdd86 100644 --- a/Localization/StringsConvertor/input/zh_CN/app.json +++ b/Localization/StringsConvertor/input/zh_CN/app.json @@ -67,7 +67,7 @@ "done": "完成", "confirm": "确认", "continue": "继续", - "compose": "Compose", + "compose": "撰写", "cancel": "取消", "discard": "放弃", "try_again": "再试一次", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "不会显示来自其它服务器的关注者" }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "不会显示来自其它服务器的关注" }, "search": { "title": "搜索", From dfb84fdb5bad9258b37246908cf618e2bc42ae48 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 15:07:45 +0800 Subject: [PATCH 35/87] chore: update i18n resources --- Mastodon/Generated/Strings.swift | 10 +++ .../Resources/ar.lproj/Localizable.strings | 3 + .../Resources/ca.lproj/Localizable.strings | 3 + .../Resources/de.lproj/Localizable.strings | 3 + .../Resources/en.lproj/Localizable.strings | 3 + .../es-419.lproj/Localizable.strings | 3 + .../Resources/es.lproj/Localizable.strings | 3 + .../Resources/fr.lproj/Localizable.strings | 3 + .../Resources/gd-GB.lproj/Localizable.strings | 3 + .../Resources/ja.lproj/Localizable.strings | 3 + .../Resources/ku-TR.lproj/Localizable.strings | 67 ++++++++++--------- .../ku-TR.lproj/Localizable.stringsdict | 4 +- .../Resources/nl.lproj/Localizable.strings | 3 + .../Resources/ru.lproj/Localizable.strings | 3 + .../Resources/th.lproj/Localizable.strings | 3 + .../zh-Hans.lproj/Localizable.strings | 3 + 16 files changed, 86 insertions(+), 34 deletions(-) diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift index 93cc4ca38..ebf9869c4 100644 --- a/Mastodon/Generated/Strings.swift +++ b/Mastodon/Generated/Strings.swift @@ -106,6 +106,8 @@ internal enum L10n { } /// 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 internal static let confirm = L10n.tr("Localizable", "Common.Controls.Actions.Confirm") /// Continue @@ -523,6 +525,14 @@ internal enum L10n { /// Your Favorites 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 { /// Home internal static let title = L10n.tr("Localizable", "Scene.HomeTimeline.Title") diff --git a/Mastodon/Resources/ar.lproj/Localizable.strings b/Mastodon/Resources/ar.lproj/Localizable.strings index 5950546a9..8681e584d 100644 --- a/Mastodon/Resources/ar.lproj/Localizable.strings +++ b/Mastodon/Resources/ar.lproj/Localizable.strings @@ -28,6 +28,7 @@ Please check your internet connection."; "Common.Controls.Actions.Back" = "العودة"; "Common.Controls.Actions.BlockDomain" = "حظر %@"; "Common.Controls.Actions.Cancel" = "إلغاء"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "تأكيد"; "Common.Controls.Actions.Continue" = "واصل"; "Common.Controls.Actions.CopyPhoto" = "نسخ الصورة"; @@ -190,6 +191,8 @@ uploaded to Mastodon."; اضغط على الرابط لتأكيد حسابك."; "Scene.ConfirmEmail.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.Offline" = "غير متصل"; "Scene.HomeTimeline.NavigationBarState.Published" = "تم نشره!"; diff --git a/Mastodon/Resources/ca.lproj/Localizable.strings b/Mastodon/Resources/ca.lproj/Localizable.strings index 71eb62b00..1642fc8a5 100644 --- a/Mastodon/Resources/ca.lproj/Localizable.strings +++ b/Mastodon/Resources/ca.lproj/Localizable.strings @@ -28,6 +28,7 @@ Comprova la teva connexió a Internet."; "Common.Controls.Actions.Back" = "Enrere"; "Common.Controls.Actions.BlockDomain" = "Bloqueja %@"; "Common.Controls.Actions.Cancel" = "Cancel·la"; +"Common.Controls.Actions.Compose" = "Composa"; "Common.Controls.Actions.Confirm" = "Confirma"; "Common.Controls.Actions.Continue" = "Continua"; "Common.Controls.Actions.CopyPhoto" = "Copia la foto"; @@ -190,6 +191,8 @@ carregat a Mastodon."; toca l'enllaç per a confirmar el teu compte."; "Scene.ConfirmEmail.Title" = "Una última cosa."; "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.Offline" = "Fora de línia"; "Scene.HomeTimeline.NavigationBarState.Published" = "Publicat!"; diff --git a/Mastodon/Resources/de.lproj/Localizable.strings b/Mastodon/Resources/de.lproj/Localizable.strings index 2780723ed..12fba5387 100644 --- a/Mastodon/Resources/de.lproj/Localizable.strings +++ b/Mastodon/Resources/de.lproj/Localizable.strings @@ -28,6 +28,7 @@ Bitte überprüfe deine Internetverbindung."; "Common.Controls.Actions.Back" = "Zurück"; "Common.Controls.Actions.BlockDomain" = "%@ blockieren"; "Common.Controls.Actions.Cancel" = "Abbrechen"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Bestätigen"; "Common.Controls.Actions.Continue" = "Fortfahren"; "Common.Controls.Actions.CopyPhoto" = "Foto kopieren"; @@ -190,6 +191,8 @@ kann nicht auf Mastodon hochgeladen werden."; tippe darin auf den Link, um Dein Konto zu bestätigen."; "Scene.ConfirmEmail.Title" = "Noch eine letzte Sache."; "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.Offline" = "Offline"; "Scene.HomeTimeline.NavigationBarState.Published" = "Veröffentlicht!"; diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings index a8852675c..0f3ed66ae 100644 --- a/Mastodon/Resources/en.lproj/Localizable.strings +++ b/Mastodon/Resources/en.lproj/Localizable.strings @@ -28,6 +28,7 @@ Please check your internet connection."; "Common.Controls.Actions.Back" = "Back"; "Common.Controls.Actions.BlockDomain" = "Block %@"; "Common.Controls.Actions.Cancel" = "Cancel"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Confirm"; "Common.Controls.Actions.Continue" = "Continue"; "Common.Controls.Actions.CopyPhoto" = "Copy Photo"; @@ -190,6 +191,8 @@ uploaded to Mastodon."; tap the link to confirm your account."; "Scene.ConfirmEmail.Title" = "One last thing."; "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.Offline" = "Offline"; "Scene.HomeTimeline.NavigationBarState.Published" = "Published!"; diff --git a/Mastodon/Resources/es-419.lproj/Localizable.strings b/Mastodon/Resources/es-419.lproj/Localizable.strings index 209502b26..3ffd12049 100644 --- a/Mastodon/Resources/es-419.lproj/Localizable.strings +++ b/Mastodon/Resources/es-419.lproj/Localizable.strings @@ -28,6 +28,7 @@ Por favor, revisá tu conexión a Internet."; "Common.Controls.Actions.Back" = "Volver"; "Common.Controls.Actions.BlockDomain" = "Bloquear a %@"; "Common.Controls.Actions.Cancel" = "Cancelar"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Confirmar"; "Common.Controls.Actions.Continue" = "Continuar"; "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."; "Scene.ConfirmEmail.Title" = "Una última cosa."; "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.Offline" = "Desconectado"; "Scene.HomeTimeline.NavigationBarState.Published" = "¡Enviado!"; diff --git a/Mastodon/Resources/es.lproj/Localizable.strings b/Mastodon/Resources/es.lproj/Localizable.strings index 1fffc928a..5e7f9afbe 100644 --- a/Mastodon/Resources/es.lproj/Localizable.strings +++ b/Mastodon/Resources/es.lproj/Localizable.strings @@ -28,6 +28,7 @@ Por favor, revise su conexión a internet."; "Common.Controls.Actions.Back" = "Atrás"; "Common.Controls.Actions.BlockDomain" = "Bloquear %@"; "Common.Controls.Actions.Cancel" = "Cancelar"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Confirmar"; "Common.Controls.Actions.Continue" = "Continuar"; "Common.Controls.Actions.CopyPhoto" = "Copiar foto"; @@ -190,6 +191,8 @@ subirse a Mastodon."; pulsa en el enlace para confirmar tu cuenta."; "Scene.ConfirmEmail.Title" = "Una última cosa."; "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.Offline" = "Sin Conexión"; "Scene.HomeTimeline.NavigationBarState.Published" = "¡Publicado!"; diff --git a/Mastodon/Resources/fr.lproj/Localizable.strings b/Mastodon/Resources/fr.lproj/Localizable.strings index 76df6b600..9514a7a5e 100644 --- a/Mastodon/Resources/fr.lproj/Localizable.strings +++ b/Mastodon/Resources/fr.lproj/Localizable.strings @@ -28,6 +28,7 @@ Veuillez vérifier votre accès à Internet."; "Common.Controls.Actions.Back" = "Retour"; "Common.Controls.Actions.BlockDomain" = "Bloquer %@"; "Common.Controls.Actions.Cancel" = "Annuler"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Confirmer"; "Common.Controls.Actions.Continue" = "Continuer"; "Common.Controls.Actions.CopyPhoto" = "Copier la photo"; @@ -190,6 +191,8 @@ téléversé sur Mastodon."; tapotez le lien pour confirmer votre compte."; "Scene.ConfirmEmail.Title" = "Une dernière chose."; "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.Offline" = "Hors ligne"; "Scene.HomeTimeline.NavigationBarState.Published" = "Publié!"; diff --git a/Mastodon/Resources/gd-GB.lproj/Localizable.strings b/Mastodon/Resources/gd-GB.lproj/Localizable.strings index 6c01adb0a..3f80f6411 100644 --- a/Mastodon/Resources/gd-GB.lproj/Localizable.strings +++ b/Mastodon/Resources/gd-GB.lproj/Localizable.strings @@ -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.BlockDomain" = "Bac %@"; "Common.Controls.Actions.Cancel" = "Sguir dheth"; +"Common.Controls.Actions.Compose" = "Sgrìobh"; "Common.Controls.Actions.Confirm" = "Dearbh"; "Common.Controls.Actions.Continue" = "Lean air adhart"; "Common.Controls.Actions.CopyPhoto" = "Dèan lethbhreac dhen dealbh"; @@ -190,6 +191,8 @@ a luchdadh suas gu Mastodon."; thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.ConfirmEmail.Title" = "Aon rud eile."; "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.Offline" = "Far loidhne"; "Scene.HomeTimeline.NavigationBarState.Published" = "Chaidh fhoillseachadh!"; diff --git a/Mastodon/Resources/ja.lproj/Localizable.strings b/Mastodon/Resources/ja.lproj/Localizable.strings index beadccf22..98bf71639 100644 --- a/Mastodon/Resources/ja.lproj/Localizable.strings +++ b/Mastodon/Resources/ja.lproj/Localizable.strings @@ -28,6 +28,7 @@ "Common.Controls.Actions.Back" = "戻る"; "Common.Controls.Actions.BlockDomain" = "%@をブロック"; "Common.Controls.Actions.Cancel" = "キャンセル"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "確認"; "Common.Controls.Actions.Continue" = "続ける"; "Common.Controls.Actions.CopyPhoto" = "写真をコピー"; @@ -184,6 +185,8 @@ "Scene.ConfirmEmail.Subtitle" = "先程 %@ にメールを送信しました。リンクをタップしてアカウントを確認してください。"; "Scene.ConfirmEmail.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.Offline" = "オフライン"; "Scene.HomeTimeline.NavigationBarState.Published" = "投稿しました!"; diff --git a/Mastodon/Resources/ku-TR.lproj/Localizable.strings b/Mastodon/Resources/ku-TR.lproj/Localizable.strings index 345f10cf9..7f84febe0 100644 --- a/Mastodon/Resources/ku-TR.lproj/Localizable.strings +++ b/Mastodon/Resources/ku-TR.lproj/Localizable.strings @@ -28,6 +28,7 @@ Jkx girêdana înternetê xwe kontrol 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"; @@ -90,7 +91,7 @@ Jkx girêdana înternetê xwe kontrol bike."; "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" = "Toggle Reblog on Post"; +"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"; @@ -134,25 +135,25 @@ Profîla te ji wan ra wiha xuya dike."; "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" = "Dismiss Account Switcher"; +"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" = "Custom Emoji Picker"; +"Scene.Compose.Accessibility.CustomEmojiPicker" = "Hilbijêrê emojî yên kesanekirî"; "Scene.Compose.Accessibility.DisableContentWarning" = "Hişyariya naverokê neçalak bike"; -"Scene.Compose.Accessibility.EnableContentWarning" = "Enable Content Warning"; +"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" = "Describe the photo for the visually-impaired..."; -"Scene.Compose.Attachment.DescriptionVideo" = "Describe the video for the visually-impaired..."; +"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" = "Space to add"; +"Scene.Compose.AutoComplete.SpaceToAdd" = "Bicîhkirinê tevlî bike"; "Scene.Compose.ComposeAction" = "Biweşîne"; -"Scene.Compose.ContentInputPlaceholder" = "Type or paste what’s on your mind"; -"Scene.Compose.ContentWarning.Placeholder" = "Write an accurate warning here..."; +"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"; @@ -182,14 +183,16 @@ Profîla te ji wan ra wiha xuya dike."; "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" = "We just sent you an email. Check your junk folder if you haven’t."; +"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" = "Check your inbox."; -"Scene.ConfirmEmail.Subtitle" = "We just sent an email to %@, -tap the link to confirm your account."; +"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!"; @@ -250,13 +253,13 @@ tap the link to confirm your account."; "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" = "Are there any other posts you’d like to add to the report?"; -"Scene.Report.Content2" = "Is there anything the moderators should know about this report?"; +"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" = "Type or paste additional comments"; +"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"; @@ -306,17 +309,17 @@ Her kîjan rajekar be."; "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 is open source software. You can report issues on GitHub at %@ (%@)"; -"Scene.Settings.Keyboard.CloseSettingsWindow" = "Close Settings Window"; +"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" = "Account Settings"; -"Scene.Settings.Section.BoringZone.Privacy" = "Privacy Policy"; -"Scene.Settings.Section.BoringZone.Terms" = "Terms of Service"; -"Scene.Settings.Section.BoringZone.Title" = "The Boring Zone"; -"Scene.Settings.Section.Notifications.Boosts" = "Reblogs my post"; +"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"; @@ -326,21 +329,21 @@ Her kîjan rajekar be."; "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" = "Disable animated avatars"; -"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "Disable animated emojis"; +"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" = "True black dark mode"; -"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "Use default browser to open links"; -"Scene.Settings.Section.SpicyZone.Clear" = "Clear Media Cache"; -"Scene.Settings.Section.SpicyZone.Signout" = "Sign Out"; -"Scene.Settings.Section.SpicyZone.Title" = "The Spicy Zone"; +"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" = "Post from %@"; +"Scene.Thread.Title" = "Şandî ji %@"; "Scene.Welcome.Slogan" = "Torên civakî di destên te de."; -"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; +"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"; \ No newline at end of file diff --git a/Mastodon/Resources/ku-TR.lproj/Localizable.stringsdict b/Mastodon/Resources/ku-TR.lproj/Localizable.stringsdict index 064b8bf2b..8ae1b812a 100644 --- a/Mastodon/Resources/ku-TR.lproj/Localizable.stringsdict +++ b/Mastodon/Resources/ku-TR.lproj/Localizable.stringsdict @@ -109,9 +109,9 @@ NSStringFormatValueTypeKey ld one - 1 reblog + 1 ji nû ve nivîsandin other - %ld reblogs + %ld ji nû ve nivîsandin plural.count.vote diff --git a/Mastodon/Resources/nl.lproj/Localizable.strings b/Mastodon/Resources/nl.lproj/Localizable.strings index 1ebda1172..9c84e138f 100644 --- a/Mastodon/Resources/nl.lproj/Localizable.strings +++ b/Mastodon/Resources/nl.lproj/Localizable.strings @@ -27,6 +27,7 @@ "Common.Controls.Actions.Back" = "Terug"; "Common.Controls.Actions.BlockDomain" = "Blokkeer %@"; "Common.Controls.Actions.Cancel" = "Annuleren"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Bevestigen"; "Common.Controls.Actions.Continue" = "Doorgaan"; "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."; "Scene.ConfirmEmail.Title" = "Nog één ding."; "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.Offline" = "Offline"; "Scene.HomeTimeline.NavigationBarState.Published" = "Gepubliceerd!"; diff --git a/Mastodon/Resources/ru.lproj/Localizable.strings b/Mastodon/Resources/ru.lproj/Localizable.strings index 3a8adbbab..1a4f92fc6 100644 --- a/Mastodon/Resources/ru.lproj/Localizable.strings +++ b/Mastodon/Resources/ru.lproj/Localizable.strings @@ -28,6 +28,7 @@ "Common.Controls.Actions.Back" = "Назад"; "Common.Controls.Actions.BlockDomain" = "Заблокировать %@"; "Common.Controls.Actions.Cancel" = "Отмена"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "Подтвердить"; "Common.Controls.Actions.Continue" = "Продолжить"; "Common.Controls.Actions.CopyPhoto" = "Скопировать изображение"; @@ -200,6 +201,8 @@ подтвердить свою учётную запись."; "Scene.ConfirmEmail.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.Offline" = "Не в сети"; "Scene.HomeTimeline.NavigationBarState.Published" = "Опубликовано!"; diff --git a/Mastodon/Resources/th.lproj/Localizable.strings b/Mastodon/Resources/th.lproj/Localizable.strings index a61b1d15f..d05bb5834 100644 --- a/Mastodon/Resources/th.lproj/Localizable.strings +++ b/Mastodon/Resources/th.lproj/Localizable.strings @@ -28,6 +28,7 @@ "Common.Controls.Actions.Back" = "ย้อนกลับ"; "Common.Controls.Actions.BlockDomain" = "ปิดกั้น %@"; "Common.Controls.Actions.Cancel" = "ยกเลิก"; +"Common.Controls.Actions.Compose" = "Compose"; "Common.Controls.Actions.Confirm" = "ยืนยัน"; "Common.Controls.Actions.Continue" = "ดำเนินการต่อ"; "Common.Controls.Actions.CopyPhoto" = "คัดลอกรูปภาพ"; @@ -190,6 +191,8 @@ แตะที่ลิงก์เพื่อยืนยันบัญชีของคุณ"; "Scene.ConfirmEmail.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.Offline" = "ออฟไลน์"; "Scene.HomeTimeline.NavigationBarState.Published" = "เผยแพร่แล้ว!"; diff --git a/Mastodon/Resources/zh-Hans.lproj/Localizable.strings b/Mastodon/Resources/zh-Hans.lproj/Localizable.strings index 21c41a15d..7a6b02032 100644 --- a/Mastodon/Resources/zh-Hans.lproj/Localizable.strings +++ b/Mastodon/Resources/zh-Hans.lproj/Localizable.strings @@ -28,6 +28,7 @@ "Common.Controls.Actions.Back" = "返回"; "Common.Controls.Actions.BlockDomain" = "屏蔽 %@"; "Common.Controls.Actions.Cancel" = "取消"; +"Common.Controls.Actions.Compose" = "撰写"; "Common.Controls.Actions.Confirm" = "确认"; "Common.Controls.Actions.Continue" = "继续"; "Common.Controls.Actions.CopyPhoto" = "拷贝照片"; @@ -190,6 +191,8 @@ 点击链接确认你的帐户。"; "Scene.ConfirmEmail.Title" = "最后一件事。"; "Scene.Favorite.Title" = "你的喜欢"; +"Scene.Follower.Footer" = "不会显示来自其它服务器的关注者"; +"Scene.Following.Footer" = "不会显示来自其它服务器的关注"; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "查看新帖子"; "Scene.HomeTimeline.NavigationBarState.Offline" = "离线"; "Scene.HomeTimeline.NavigationBarState.Published" = "已发送"; From 206beb6d19d46fc71f4b62ee8b79eedb37dd655d Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 16:00:42 +0800 Subject: [PATCH 36/87] chore: update following/follower list footer display logic --- .../Follower/FollowerListViewModel+Diffable.swift | 6 +++++- .../Follower/FollowerListViewModel+State.swift | 2 +- .../Following/FollowingListViewModel+Diffable.swift | 7 ++++++- .../Following/FollowingListViewModel+State.swift | 12 ------------ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift index c048e1723..fc9f31779 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+Diffable.swift @@ -48,7 +48,11 @@ extension FollowerListViewModel { case is State.Idle, is State.Loading, is State.Fail: snapshot.appendItems([.bottomLoader], toSection: .main) case is State.NoMore: - let text = "Followers from other servers are not displayed." + 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 diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift index 876933181..30621f6a3 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift @@ -155,7 +155,7 @@ extension FollowerListViewModel.State { let maxID = response.link?.maxID - if hasNewAppend, maxID != nil { + if maxID != nil { stateMachine.enter(Idle.self) } else { stateMachine.enter(NoMore.self) diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift index 58af276d0..dc6f1f6fd 100644 --- a/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel+Diffable.swift @@ -48,7 +48,12 @@ extension FollowingListViewModel { case is State.Idle, is State.Loading, is State.Fail: snapshot.appendItems([.bottomLoader], toSection: .main) case is State.NoMore: - break + 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 } diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift index d5c30b43a..e6fadf7f8 100644 --- a/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift @@ -179,18 +179,6 @@ extension FollowingListViewModel.State { override func didEnter(from previousState: GKState?) { super.didEnter(from: previousState) - guard let viewModel = viewModel, let _ = stateMachine else { return } - guard let diffableDataSource = viewModel.diffableDataSource else { - assertionFailure() - return - } - DispatchQueue.main.async { - var snapshot = diffableDataSource.snapshot() - snapshot.deleteItems([.bottomLoader]) - let header = UserItem.bottomHeader(text: "Followers from other servers are not displayed") - snapshot.appendItems([header], toSection: .main) - diffableDataSource.apply(snapshot, animatingDifferences: false) - } } } } From c9c0aaf148034d46c1218a85067461d90579f50b Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 16:01:22 +0800 Subject: [PATCH 37/87] fix: follower list pagination not works issue --- Mastodon/Service/APIService/APIService+Follower.swift | 5 +++++ .../MastodonSDK/API/Mastodon+API+Account+Followers.swift | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Mastodon/Service/APIService/APIService+Follower.swift b/Mastodon/Service/APIService/APIService+Follower.swift index db29a0a29..f75d2420d 100644 --- a/Mastodon/Service/APIService/APIService+Follower.swift +++ b/Mastodon/Service/APIService/APIService+Follower.swift @@ -23,10 +23,15 @@ extension APIService { let authorization = authorizationBox.userAuthorization let requestMastodonUserID = authorizationBox.userID + let query = Mastodon.API.Account.FollowerQuery( + maxID: maxID, + limit: nil + ) return Mastodon.API.Account.followers( session: session, domain: domain, userID: userID, + query: query, authorization: authorization ) .flatMap { response -> AnyPublisher, Error> in diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Followers.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Followers.swift index b09a5f07b..a900a1c12 100644 --- a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Followers.swift +++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Followers.swift @@ -35,11 +35,12 @@ extension Mastodon.API.Account { session: URLSession, domain: String, userID: Mastodon.Entity.Account.ID, + query: FollowerQuery, authorization: Mastodon.API.OAuth.Authorization ) -> AnyPublisher, Error> { let request = Mastodon.API.get( url: followersEndpointURL(domain: domain, userID: userID), - query: nil, + query: query, authorization: authorization ) return session.dataTaskPublisher(for: request) From 6d7de85f6272faab92a7725a5527d5bd780a7341 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 16:02:46 +0800 Subject: [PATCH 38/87] fix: account switcher popover too small issue --- Mastodon/Scene/Root/ContentSplitViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mastodon/Scene/Root/ContentSplitViewController.swift b/Mastodon/Scene/Root/ContentSplitViewController.swift index 850b1429f..8ca597872 100644 --- a/Mastodon/Scene/Root/ContentSplitViewController.swift +++ b/Mastodon/Scene/Root/ContentSplitViewController.swift @@ -101,7 +101,8 @@ extension ContentSplitViewController: SidebarViewControllerDelegate { let accountListViewController = coordinator.present(scene: .accountList, from: nil, transition: .popover(sourceView: sourceView)) as! AccountListViewController accountListViewController.dragIndicatorView.barView.isHidden = true - accountListViewController.preferredContentSize = CGSize(width: 300, height: 320) + // content width needs > 300 to make checkmark display + accountListViewController.preferredContentSize = CGSize(width: 375, height: 400) } } From 07eab320f40b7e643d0465ad45b4633a2c4fb594 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 16:03:34 +0800 Subject: [PATCH 39/87] fix: iPad layout update not take care of search tab selection logic issue --- .../Root/MainTab/MainTabBarController.swift | 4 ++ .../Scene/Root/RootSplitViewController.swift | 50 +++++++++++++------ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index d34c85531..e76db6b3a 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -351,6 +351,10 @@ extension MainTabBarController { return viewController(of: NotificationViewController.self) } + var searchViewController: SearchViewController? { + return viewController(of: SearchViewController.self) + } + } // MARK: - UITabBarControllerDelegate diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index 7c03287f1..13df6f889 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -19,6 +19,8 @@ final class RootSplitViewController: UISplitViewController, NeedsDependency { weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } + private var isPrimaryDisplay = false + private(set) lazy var contentSplitViewController: ContentSplitViewController = { let contentSplitViewController = ContentSplitViewController() contentSplitViewController.context = context @@ -79,13 +81,6 @@ extension RootSplitViewController { super.viewDidLoad() updateBehavior(size: view.frame.size) - contentSplitViewController.$currentSupplementaryTab - .receive(on: DispatchQueue.main) - .sink { [weak self] _ in - guard let self = self else { return } - self.updateBehavior(size: self.view.frame.size) - } - .store(in: &disposeBag) setupBackground(theme: ThemeService.shared.currentTheme.value) ThemeService.shared.currentTheme @@ -97,6 +92,12 @@ extension RootSplitViewController { .store(in: &disposeBag) } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + updateBehavior(size: view.frame.size) + } + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) @@ -109,15 +110,23 @@ extension RootSplitViewController { } private func updateBehavior(size: CGSize) { - switch contentSplitViewController.currentSupplementaryTab { - case .search: + if size.width > 960 { + show(.primary) + isPrimaryDisplay = true + + } else { hide(.primary) + isPrimaryDisplay = false + } + + switch (contentSplitViewController.currentSupplementaryTab, isPrimaryDisplay) { + case (.search, true): + // needs switch to other tab when primary display + // use FIFO queue save tab history + contentSplitViewController.currentSupplementaryTab = .home default: - if size.width > 960 { - show(.primary) - } else { - hide(.primary) - } + // do nothing + break } } @@ -140,7 +149,11 @@ extension RootSplitViewController: ContentSplitViewControllerDelegate { return } switch tab { - case .search: + case .search: + guard isPrimaryDisplay else { + // only control search tab behavior when primary display + fallthrough + } guard let navigationController = searchViewController.navigationController else { return } if navigationController.viewControllers.count == 1 { searchViewController.searchBarTapPublisher.send() @@ -165,7 +178,7 @@ extension RootSplitViewController: ContentSplitViewControllerDelegate { // MARK: - UISplitViewControllerDelegate extension RootSplitViewController: UISplitViewControllerDelegate { - private static func transform(from: UITabBarController, to: UITabBarController) { + private static func transform(from: UITabBarController, to: UITabBarController) { let sourceNavigationControllers = from.viewControllers ?? [] let targetNavigationControllers = to.viewControllers ?? [] @@ -181,6 +194,11 @@ extension RootSplitViewController: UISplitViewControllerDelegate { to.selectedIndex = from.selectedIndex } + private static func transform(from: UINavigationController, to: UINavigationController) { + let viewControllers = from.popToRootViewController(animated: false) ?? [] + to.viewControllers.append(contentsOf: viewControllers) + } + // .regular to .compact func splitViewController( _ svc: UISplitViewController, From 30b2a35b84d685f2def2b1c8cfbb2181bd6918bf Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 16:12:20 +0800 Subject: [PATCH 40/87] feat: implement following list --- Mastodon.xcodeproj/project.pbxproj | 4 + .../xcschemes/xcschememanagement.plist | 8 +- .../FollowerListViewModel+State.swift | 2 +- .../FollowingListViewModel+State.swift | 2 +- .../APIService/APIService+Following.swift | 70 ++++++++++++++++ .../API/Mastodon+API+Account+Following.swift | 82 +++++++++++++++++++ 6 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 Mastodon/Service/APIService/APIService+Following.swift create mode 100644 MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Following.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 8408f3ac3..98cff7ec9 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -320,6 +320,7 @@ DB66728C25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */; }; DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.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 */; }; DB68045B2636DC6A00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; }; DB6804662636DC9000430867 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D939AB425EDD8A90076FA61 /* String.swift */; }; DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; }; @@ -1139,6 +1140,7 @@ DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ComposeViewModel+DataSource.swift"; sourceTree = ""; }; DB66729525F9F91600D60309 /* ComposeStatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusSection.swift; sourceTree = ""; }; DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = ""; }; + DB67D08327312970006A36CF /* APIService+Following.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Following.swift"; sourceTree = ""; }; DB68045A2636DC6A00430867 /* MastodonNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonNotification.swift; sourceTree = ""; }; 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 = ""; }; @@ -2326,6 +2328,7 @@ 2D34D9DA261494120081BFC0 /* APIService+Search.swift */, 0F202212261351F5000C64BF /* APIService+HashtagTimeline.swift */, DB6B74F9272FC2B500C70B6E /* APIService+Follower.swift */, + DB67D08327312970006A36CF /* APIService+Following.swift */, DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */, 5B24BBE1262DB19100A9381B /* APIService+Report.swift */, DBAE3F932616E28B004B8251 /* APIService+Follow.swift */, @@ -4125,6 +4128,7 @@ 2D82B9FF25E7863200E36F0F /* OnboardingViewControllerAppearance.swift in Sources */, 5DF1054725F8870E00D6C0D4 /* VideoPlayerViewModel.swift in Sources */, DB73BF43271192BB00781945 /* InstanceService.swift in Sources */, + DB67D08427312970006A36CF /* APIService+Following.swift in Sources */, DBA9443A265CC0FC00C537E1 /* Fields.swift in Sources */, 2DE0FAC12615F04D00CDF649 /* RecommendHashTagSection.swift in Sources */, DBA5E7A5263BD28C004598BB /* ContextMenuImagePreviewViewModel.swift in Sources */, diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 2d2dd1932..5a5418919 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 36 + 37 CoreDataStack.xcscheme_^#shared#^_ orderHint - 35 + 36 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -97,7 +97,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 38 + 35 MastodonIntents.xcscheme_^#shared#^_ @@ -117,7 +117,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 37 + 38 SuppressBuildableAutocreation diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift index 30621f6a3..43e532673 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewModel+State.swift @@ -155,7 +155,7 @@ extension FollowerListViewModel.State { let maxID = response.link?.maxID - if maxID != nil { + if hasNewAppend && maxID != nil { stateMachine.enter(Idle.self) } else { stateMachine.enter(NoMore.self) diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift index e6fadf7f8..0ec3d6262 100644 --- a/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel+State.swift @@ -128,7 +128,7 @@ extension FollowingListViewModel.State { return } - viewModel.context.apiService.followers( + viewModel.context.apiService.following( userID: userID, maxID: maxID, authorizationBox: activeMastodonAuthenticationBox diff --git a/Mastodon/Service/APIService/APIService+Following.swift b/Mastodon/Service/APIService/APIService+Following.swift new file mode 100644 index 000000000..8f477d6ec --- /dev/null +++ b/Mastodon/Service/APIService/APIService+Following.swift @@ -0,0 +1,70 @@ +// +// APIService+Following.swift +// Mastodon +// +// Created by Cirno MainasuK on 2021-11-2. +// + +import UIKit +import Combine +import CoreData +import CoreDataStack +import CommonOSLog +import MastodonSDK + +extension APIService { + + func following( + userID: Mastodon.Entity.Account.ID, + maxID: String?, + authorizationBox: MastodonAuthenticationBox + ) -> AnyPublisher, Error> { + let domain = authorizationBox.domain + let authorization = authorizationBox.userAuthorization + let requestMastodonUserID = authorizationBox.userID + + let query = Mastodon.API.Account.FollowingQuery( + maxID: maxID, + limit: nil + ) + return Mastodon.API.Account.following( + session: session, + domain: domain, + userID: userID, + query: query, + authorization: authorization + ) + .flatMap { response -> AnyPublisher, Error> in + let managedObjectContext = self.backgroundManagedObjectContext + return managedObjectContext.performChanges { + let requestMastodonUserRequest = MastodonUser.sortedFetchRequest + requestMastodonUserRequest.predicate = MastodonUser.predicate(domain: domain, id: requestMastodonUserID) + requestMastodonUserRequest.fetchLimit = 1 + guard let requestMastodonUser = managedObjectContext.safeFetch(requestMastodonUserRequest).first else { return } + + for entity in response.value { + _ = APIService.CoreData.createOrMergeMastodonUser( + into: managedObjectContext, + for: requestMastodonUser, + in: domain, + entity: entity, + userCache: nil, + networkDate: response.networkDate, + log: .api + ) + } + } + .tryMap { result -> Mastodon.Response.Content<[Mastodon.Entity.Account]> in + switch result { + case .success: + return response + case .failure(let error): + throw error + } + } + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + } + +} diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Following.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Following.swift new file mode 100644 index 000000000..c992c7584 --- /dev/null +++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+Following.swift @@ -0,0 +1,82 @@ +// +// Mastodon+API+Account+Following.swift +// +// +// Created by Cirno MainasuK on 2021-11-2. +// + +import Foundation +import Combine + +extension Mastodon.API.Account { + + static func followingEndpointURL(domain: String, userID: Mastodon.Entity.Account.ID) -> URL { + return Mastodon.API.endpointURL(domain: domain) + .appendingPathComponent("accounts") + .appendingPathComponent(userID) + .appendingPathComponent("following") + } + + /// Following + /// + /// Accounts which the given account is following, if network is not hidden by the account owner. + /// + /// - Since: 0.0.0 + /// - Version: 3.4.1 + /// # Reference + /// [Document](https://docs.joinmastodon.org/methods/accounts/) + /// - Parameters: + /// - session: `URLSession` + /// - domain: Mastodon instance domain. e.g. "example.com" + /// - userID: ID of the account in the database + /// - authorization: User token + /// - Returns: `AnyPublisher` contains `[Account]` nested in the response + public static func following( + session: URLSession, + domain: String, + userID: Mastodon.Entity.Account.ID, + query: FollowingQuery, + authorization: Mastodon.API.OAuth.Authorization + ) -> AnyPublisher, Error> { + let request = Mastodon.API.get( + url: followingEndpointURL(domain: domain, userID: userID), + query: query, + authorization: authorization + ) + return session.dataTaskPublisher(for: request) + .tryMap { data, response in + let value = try Mastodon.API.decode(type: [Mastodon.Entity.Account].self, from: data, response: response) + return Mastodon.Response.Content(value: value, response: response) + } + .eraseToAnyPublisher() + } + + public struct FollowingQuery: Codable, GetQuery { + + public let maxID: String? + public let limit: Int? // default 40 + + enum CodingKeys: String, CodingKey { + case maxID = "max_id" + case limit + } + + public init( + maxID: String?, + limit: Int? + ) { + self.maxID = maxID + self.limit = limit + } + + var queryItems: [URLQueryItem]? { + var items: [URLQueryItem] = [] + maxID.flatMap { items.append(URLQueryItem(name: "max_id", value: $0)) } + limit.flatMap { items.append(URLQueryItem(name: "limit", value: String($0))) } + guard !items.isEmpty else { return nil } + return items + } + + } + +} From a7f6b1d222633bd6e8d3f1703aa31001330d4b9a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 2 Nov 2021 11:38:48 +0100 Subject: [PATCH 41/87] New translations app.json (Spanish) --- Localization/StringsConvertor/input/es_ES/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/es_ES/app.json b/Localization/StringsConvertor/input/es_ES/app.json index 1710318b9..72967c40f 100644 --- a/Localization/StringsConvertor/input/es_ES/app.json +++ b/Localization/StringsConvertor/input/es_ES/app.json @@ -67,7 +67,7 @@ "done": "Hecho", "confirm": "Confirmar", "continue": "Continuar", - "compose": "Compose", + "compose": "Redactar", "cancel": "Cancelar", "discard": "Descartar", "try_again": "Inténtalo de nuevo", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "No se muestran los seguidores de otros servidores." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "No se muestran los seguidos de otros servidores." }, "search": { "title": "Buscar", From 865718351d3230a447618a85ea855690c8fd5a17 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 19:15:46 +0800 Subject: [PATCH 42/87] feat: update wizard for new iPad design --- Mastodon.xcodeproj/project.pbxproj | 16 +- Mastodon/Coordinator/SceneCoordinator.swift | 24 +- .../Welcome/View/WizardCardView.swift | 7 + .../MainTab/MainTabBarController+Wizard.swift | 137 ------------ .../Root/MainTab/MainTabBarController.swift | 47 ++-- .../Scene/Root/RootSplitViewController.swift | 87 ++++++++ .../Root/Sidebar/SidebarViewController.swift | 1 + .../Scene/Root/Sidebar/SidebarViewModel.swift | 9 +- .../Scene/Wizard/WizardViewController.swift | 211 ++++++++++++++++++ 9 files changed, 371 insertions(+), 168 deletions(-) delete mode 100644 Mastodon/Scene/Root/MainTab/MainTabBarController+Wizard.swift create mode 100644 Mastodon/Scene/Wizard/WizardViewController.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 98cff7ec9..619baa12b 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -315,12 +315,12 @@ DB6180F826391D660018D199 /* MediaPreviewingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6180F726391D660018D199 /* MediaPreviewingViewController.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 */; }; - DB647C5726F1E97300F7F82C /* MainTabBarController+Wizard.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB647C5626F1E97300F7F82C /* MainTabBarController+Wizard.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 */; }; DB66729625F9F91600D60309 /* ComposeStatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB66729525F9F91600D60309 /* ComposeStatusSection.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 */; }; DB68045B2636DC6A00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; }; DB6804662636DC9000430867 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D939AB425EDD8A90076FA61 /* String.swift */; }; DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; }; @@ -1135,12 +1135,12 @@ DB6180F726391D660018D199 /* MediaPreviewingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewingViewController.swift; sourceTree = ""; }; DB6180F926391F2E0018D199 /* MediaPreviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewViewModel.swift; sourceTree = ""; }; DB63BE7E268DD1070011D3F9 /* NotificationViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationViewController+StatusProvider.swift"; sourceTree = ""; }; - DB647C5626F1E97300F7F82C /* MainTabBarController+Wizard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainTabBarController+Wizard.swift"; sourceTree = ""; }; DB647C5826F1EA2700F7F82C /* WizardPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardPreference.swift; sourceTree = ""; }; DB66728B25F9F8DC00D60309 /* ComposeViewModel+DataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ComposeViewModel+DataSource.swift"; sourceTree = ""; }; DB66729525F9F91600D60309 /* ComposeStatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusSection.swift; sourceTree = ""; }; DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = ""; }; DB67D08327312970006A36CF /* APIService+Following.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Following.swift"; sourceTree = ""; }; + DB67D08527312E67006A36CF /* WizardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardViewController.swift; sourceTree = ""; }; DB68045A2636DC6A00430867 /* MastodonNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonNotification.swift; sourceTree = ""; }; 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 = ""; }; @@ -2529,6 +2529,14 @@ path = Image; sourceTree = ""; }; + DB67D08727312E6A006A36CF /* Wizard */ = { + isa = PBXGroup; + children = ( + DB67D08527312E67006A36CF /* WizardViewController.swift */, + ); + path = Wizard; + sourceTree = ""; + }; DB6804802637CD4C00430867 /* AppShared */ = { isa = PBXGroup; children = ( @@ -2770,7 +2778,6 @@ isa = PBXGroup; children = ( DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */, - DB647C5626F1E97300F7F82C /* MainTabBarController+Wizard.swift */, ); path = MainTab; sourceTree = ""; @@ -2782,6 +2789,7 @@ DB6180E426391A500018D199 /* Transition */, DB852D1D26FB021900FC9D81 /* Root */, DB01409B25C40BB600F9F3CF /* Onboarding */, + DB67D08727312E6A006A36CF /* Wizard */, DB9F58ED26EF435800E7BBE9 /* Account */, 2D38F1D325CD463600561493 /* HomeTimeline */, 2D76316325C14BAC00929FB9 /* PublicTimeline */, @@ -4358,6 +4366,7 @@ DB71FD2C25F86A5100512AE1 /* AvatarStackContainerButton.swift in Sources */, DB87D4512609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift in Sources */, DBBC24C026A5443100398BB9 /* MastodonTheme.swift in Sources */, + DB67D08627312E67006A36CF /* WizardViewController.swift in Sources */, DBBC24B526A540AE00398BB9 /* AvatarConfigurableView.swift in Sources */, DB9A489026035963008B817C /* APIService+Media.swift in Sources */, DBFEF07726A691FB006D7ED1 /* MastodonAuthenticationBox.swift in Sources */, @@ -4371,7 +4380,6 @@ DB49A62525FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift in Sources */, DB4924E226312AB200E9DB22 /* NotificationService.swift in Sources */, DB6D9F6F2635807F008423CD /* Setting.swift in Sources */, - DB647C5726F1E97300F7F82C /* MainTabBarController+Wizard.swift in Sources */, DB6F5E38264E994A009108F4 /* AutoCompleteTopChevronView.swift in Sources */, DBB525412611ED54002F1F29 /* ProfileHeaderViewController.swift in Sources */, DB6B74F8272FBFB100C70B6E /* FollowerListViewController+Provider.swift in Sources */, diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index e7611056f..9fbb2b774 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -23,6 +23,7 @@ final public class SceneCoordinator { private(set) weak var tabBarController: MainTabBarController! private(set) weak var splitViewController: RootSplitViewController? + private(set) var wizardViewController: WizardViewController? private(set) var secondaryStackHashValues = Set() @@ -221,17 +222,34 @@ extension SceneCoordinator { extension SceneCoordinator { func setup() { + let rootViewController: UIViewController switch UIDevice.current.userInterfaceIdiom { case .phone: let viewController = MainTabBarController(context: appContext, coordinator: self) - sceneDelegate.window?.rootViewController = viewController - tabBarController = viewController + self.splitViewController = nil + self.tabBarController = viewController + rootViewController = viewController default: let splitViewController = RootSplitViewController(context: appContext, coordinator: self) self.splitViewController = splitViewController 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) { diff --git a/Mastodon/Scene/Onboarding/Welcome/View/WizardCardView.swift b/Mastodon/Scene/Onboarding/Welcome/View/WizardCardView.swift index 024fb205d..6f18afc94 100644 --- a/Mastodon/Scene/Onboarding/Welcome/View/WizardCardView.swift +++ b/Mastodon/Scene/Onboarding/Welcome/View/WizardCardView.swift @@ -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.addLine(to: CGPoint(x: rect.minX - radius, y: rect.maxY + radius + WizardCardView.bubbleArrowHeight)) 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: assertionFailure("FIXME") } diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController+Wizard.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController+Wizard.swift deleted file mode 100644 index b69a6b786..000000000 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController+Wizard.swift +++ /dev/null @@ -1,137 +0,0 @@ -// -// MainTabBarController+Wizard.swift -// Mastodon -// -// Created by Cirno MainasuK on 2021-9-15. -// - -import os.log -import UIKit - -protocol WizardDelegate: AnyObject { - func spotlight(item: MainTabBarController.Wizard.Item) -> UIBezierPath - func layoutWizardCard(_ wizard: MainTabBarController.Wizard, item: MainTabBarController.Wizard.Item) -} - -extension MainTabBarController { - class Wizard { - - let logger = Logger(subsystem: "Wizard", category: "UI") - - weak var delegate: WizardDelegate? - - private(set) var items: [Item] - - let backgroundView: UIView = { - let view = UIView() - view.backgroundColor = UIColor.black.withAlphaComponent(0.7) - return view - }() - - init() { - var items: [Item] = [] - if !UserDefaults.shared.didShowMultipleAccountSwitchWizard { - items.append(.multipleAccountSwitch) - } - self.items = items - - let backgroundTapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer - backgroundTapGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.Wizard.backgroundTapGestureRecognizerHandler(_:))) - backgroundView.addGestureRecognizer(backgroundTapGestureRecognizer) - } - } -} - -extension MainTabBarController.Wizard { - enum Item { - case multipleAccountSwitch - - var title: String { - return L10n.Scene.Wizard.newInMastodon - } - - var description: String { - switch self { - case .multipleAccountSwitch: - return L10n.Scene.Wizard.multipleAccountSwitchIntroDescription - } - } - - func markAsRead() { - switch self { - case .multipleAccountSwitch: - UserDefaults.shared.didShowMultipleAccountSwitchWizard = true - } - } - } -} - -extension MainTabBarController.Wizard { - - func setup(in view: UIView) { - assert(delegate != nil, "need set delegate before use") - - guard !items.isEmpty else { return } - - backgroundView.frame = view.bounds - backgroundView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(backgroundView) - NSLayoutConstraint.activate([ - backgroundView.topAnchor.constraint(equalTo: view.topAnchor), - backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - backgroundView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - - func consume() { - guard !items.isEmpty else { - backgroundView.removeFromSuperview() - return - } - let item = items.removeFirst() - perform(item: item) - } - - private func perform(item: Item) { - guard let delegate = delegate else { - assertionFailure() - return - } - - // prepare for reuse - prepareForReuse() - - // set wizard item read - item.markAsRead() - - // add spotlight - let spotlight = delegate.spotlight(item: item) - let maskLayer = CAShapeLayer() - let path = UIBezierPath(rect: backgroundView.bounds) - path.append(spotlight) - maskLayer.fillRule = .evenOdd - maskLayer.path = path.cgPath - backgroundView.layer.mask = maskLayer - - // layout wizard card - delegate.layoutWizardCard(self, item: item) - } - - private func prepareForReuse() { - backgroundView.subviews.forEach { subview in - subview.removeFromSuperview() - } - backgroundView.mask = nil - backgroundView.layer.mask = nil - } - -} - -extension MainTabBarController.Wizard { - @objc private func backgroundTapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) { - logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") - - consume() - } -} diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index e76db6b3a..2cb964277 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -21,8 +21,6 @@ class MainTabBarController: UITabBarController { static let avatarButtonSize = CGSize(width: 25, height: 25) let avatarButton = CircleAvatarButton() - - let wizard = Wizard() var currentTab = CurrentValueSubject(.home) @@ -108,6 +106,8 @@ class MainTabBarController: UITabBarController { var _viewControllers: [UIViewController] = [] + private(set) var isReadyForWizardAvatarButton = false + init(context: AppContext, coordinator: SceneCoordinator) { self.context = context self.coordinator = coordinator @@ -247,9 +247,6 @@ extension MainTabBarController { profileTabItem.accessibilityHint = L10n.Scene.AccountList.tabBarHint(currentUserDisplayName) } .store(in: &disposeBag) - - wizard.delegate = self - wizard.setup(in: view) let tabBarLongPressGestureRecognizer = UILongPressGestureRecognizer() tabBarLongPressGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarLongPressGestureRecognizerHandler(_:))) @@ -265,7 +262,7 @@ extension MainTabBarController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - wizard.consume() + isReadyForWizardAvatarButton = true } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { @@ -377,51 +374,57 @@ extension MainTabBarController: UITabBarControllerDelegate { } } -// MARK: - WizardDataSource -extension MainTabBarController: WizardDelegate { - func spotlight(item: Wizard.Item) -> UIBezierPath { +// MARK: - WizardViewControllerDelegate +extension MainTabBarController: WizardViewControllerDelegate { + func readyToLayoutItem(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> Bool { switch item { case .multipleAccountSwitch: - guard let avatarButtonFrameInView = avatarButtonFrameInView() else { - return UIBezierPath() - } - return UIBezierPath(ovalIn: avatarButtonFrameInView) - + return isReadyForWizardAvatarButton } } - func layoutWizardCard(_ wizard: MainTabBarController.Wizard, item: Wizard.Item) { + func layoutSpotlight(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> UIBezierPath { switch item { case .multipleAccountSwitch: - guard let avatarButtonFrameInView = avatarButtonFrameInView() else { + guard let avatarButtonFrameInView = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) else { + return UIBezierPath() + } + return UIBezierPath(ovalIn: avatarButtonFrameInView) + } + } + + func layoutWizardCard(_ wizardViewController: WizardViewController, item: WizardViewController.Item) { + switch item { + case .multipleAccountSwitch: + guard let avatarButtonFrameInView = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) else { return } let anchorView = UIView() anchorView.frame = avatarButtonFrameInView - wizard.backgroundView.addSubview(anchorView) + wizardViewController.backgroundView.addSubview(anchorView) let wizardCardView = WizardCardView() wizardCardView.arrowRectCorner = view.traitCollection.layoutDirection == .leftToRight ? .bottomRight : .bottomLeft wizardCardView.titleLabel.text = item.title wizardCardView.descriptionLabel.text = item.description - + wizardCardView.translatesAutoresizingMaskIntoConstraints = false - wizard.backgroundView.addSubview(wizardCardView) + wizardViewController.backgroundView.addSubview(wizardCardView) NSLayoutConstraint.activate([ anchorView.topAnchor.constraint(equalTo: wizardCardView.bottomAnchor, constant: 13), // 13pt spacing wizardCardView.trailingAnchor.constraint(equalTo: anchorView.centerXAnchor), - wizardCardView.widthAnchor.constraint(equalTo: wizard.backgroundView.widthAnchor, multiplier: 2.0/3.0).priority(.required - 1), + wizardCardView.widthAnchor.constraint(equalTo: wizardViewController.view.widthAnchor, multiplier: 2.0/3.0).priority(.required - 1), ]) wizardCardView.setContentHuggingPriority(.defaultLow, for: .vertical) } } - private func avatarButtonFrameInView() -> CGRect? { + private func avatarButtonFrameInWizardView(wizardView: UIView) -> CGRect? { guard let superview = avatarButton.superview else { assertionFailure() return nil } - return superview.convert(avatarButton.frame, to: view) + return superview.convert(avatarButton.frame, to: wizardView) } } diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index 13df6f889..2b3c858e0 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -241,3 +241,90 @@ extension RootSplitViewController: UISplitViewControllerDelegate { } } + +// MARK: - WizardViewControllerDelegate +extension RootSplitViewController: WizardViewControllerDelegate { + + func readyToLayoutItem(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> Bool { + guard traitCollection.horizontalSizeClass != .compact else { + return compactMainTabBarViewController.readyToLayoutItem(wizardViewController, item: item) + } + + switch item { + case .multipleAccountSwitch: + return contentSplitViewController.sidebarViewController.viewModel.isReadyForWizardAvatarButton + } + } + + + func layoutSpotlight(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> UIBezierPath { + guard traitCollection.horizontalSizeClass != .compact else { + return compactMainTabBarViewController.layoutSpotlight(wizardViewController, item: item) + } + + switch item { + case .multipleAccountSwitch: + guard let frame = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) + else { + assertionFailure() + return UIBezierPath() + } + return UIBezierPath(ovalIn: frame) + } + } + + func layoutWizardCard(_ wizardViewController: WizardViewController, item: WizardViewController.Item) { + guard traitCollection.horizontalSizeClass != .compact else { + return compactMainTabBarViewController.layoutWizardCard(wizardViewController, item: item) + } + + guard let frame = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) else { + return + } + + let anchorView = UIView() + anchorView.frame = frame + wizardViewController.backgroundView.addSubview(anchorView) + + let wizardCardView = WizardCardView() + wizardCardView.arrowRectCorner = .allCorners // no arrow + wizardCardView.titleLabel.text = item.title + wizardCardView.descriptionLabel.text = item.description + + wizardCardView.translatesAutoresizingMaskIntoConstraints = false + wizardViewController.backgroundView.addSubview(wizardCardView) + NSLayoutConstraint.activate([ + wizardCardView.centerYAnchor.constraint(equalTo: anchorView.centerYAnchor), + wizardCardView.leadingAnchor.constraint(equalTo: anchorView.trailingAnchor, constant: 20), // 20pt spacing + wizardCardView.widthAnchor.constraint(equalToConstant: 320), + ]) + wizardCardView.setContentHuggingPriority(.defaultLow, for: .vertical) + } + + private func avatarButtonFrameInWizardView(wizardView: UIView) -> CGRect? { + guard let diffableDataSource = contentSplitViewController.sidebarViewController.viewModel.diffableDataSource, + let indexPath = diffableDataSource.indexPath(for: .tab(.me)), + let cell = contentSplitViewController.sidebarViewController.collectionView.cellForItem(at: indexPath) as? SidebarListCollectionViewCell, + let contentView = cell._contentView, + let frame = sourceViewFrameInTargetView( + sourceView: contentView.avatarButton, + targetView: wizardView + ) + else { + assertionFailure() + return nil + } + return frame + } + + private func sourceViewFrameInTargetView( + sourceView: UIView, + targetView: UIView + ) -> CGRect? { + guard let superview = sourceView.superview else { + assertionFailure() + return nil + } + return superview.convert(sourceView.frame, to: targetView) + } +} diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift index 7958c5080..d2dae2478 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift @@ -125,6 +125,7 @@ extension SidebarViewController { secondaryCollectionView.observe(\.contentSize, options: [.initial, .new]) { [weak self] secondaryCollectionView, _ in guard let self = self else { return } + self.logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): secondaryCollectionView contentSize: \(secondaryCollectionView.contentSize.debugDescription)") let height = secondaryCollectionView.contentSize.height self.secondaryCollectionViewHeightLayoutConstraint.constant = height self.collectionView.contentInset.bottom = height diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift index 83abf4e6b..1f982429e 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift @@ -23,6 +23,7 @@ final class SidebarViewModel { // output var diffableDataSource: UICollectionViewDiffableDataSource? var secondaryDiffableDataSource: UICollectionViewDiffableDataSource? + private(set) var isReadyForWizardAvatarButton = false let activeMastodonAuthenticationObjectID = CurrentValueSubject(nil) @@ -170,8 +171,12 @@ extension SidebarViewModel { .setting, ] sectionSnapshot.append(items, to: nil) - _diffableDataSource.apply(sectionSnapshot, to: .main) - + // animatingDifferences must to be `true` + // otherwise the UI layout will infinity loop + _diffableDataSource.apply(sectionSnapshot, to: .main, animatingDifferences: true) { [weak self] in + guard let self = self else { return } + self.isReadyForWizardAvatarButton = true + } // secondary let _secondaryDiffableDataSource = UICollectionViewDiffableDataSource(collectionView: secondaryCollectionView) { collectionView, indexPath, item in diff --git a/Mastodon/Scene/Wizard/WizardViewController.swift b/Mastodon/Scene/Wizard/WizardViewController.swift new file mode 100644 index 000000000..2678c712d --- /dev/null +++ b/Mastodon/Scene/Wizard/WizardViewController.swift @@ -0,0 +1,211 @@ +// +// WizardViewController.swift +// Mastodon +// +// Created by Cirno MainasuK on 2021-11-2. +// + +import os.log +import UIKit +import Combine + +protocol WizardViewControllerDelegate: AnyObject { + func readyToLayoutItem(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> Bool + func layoutSpotlight(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> UIBezierPath + func layoutWizardCard(_ wizardViewController: WizardViewController, item: WizardViewController.Item) +} + +class WizardViewController: UIViewController { + + let logger = Logger(subsystem: "Wizard", category: "UI") + + var disposeBag = Set() + weak var delegate: WizardViewControllerDelegate? + + private(set) var items: [Item] = { + var items: [Item] = [] + if !UserDefaults.shared.didShowMultipleAccountSwitchWizard { + items.append(.multipleAccountSwitch) + } + return items + }() + + let pendingItem = CurrentValueSubject(nil) + let currentItem = CurrentValueSubject(nil) + + let backgroundView: UIView = { + let view = UIView() + view.backgroundColor = UIColor.black.withAlphaComponent(0.7) + return view + }() + + deinit { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) + } + +} + +extension WizardViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + setup() + + let backgroundTapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer + backgroundTapGestureRecognizer.addTarget(self, action: #selector(WizardViewController.backgroundTapGestureRecognizerHandler(_:))) + backgroundView.addGestureRecognizer(backgroundTapGestureRecognizer) + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + // Create a timer to consume pending item + Timer.publish(every: 0.5, on: .main, in: .default) + .autoconnect() + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + guard let self = self else { return } + guard self.pendingItem.value != nil else { return } + self.consume() + } + .store(in: &disposeBag) + + consume() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + invalidLayoutForCurrentItem() + } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + coordinator.animate { context in + + } completion: { [weak self] context in + guard let self = self else { return } + self.invalidLayoutForCurrentItem() + } + + } + +} + +extension WizardViewController { + enum Item { + case multipleAccountSwitch + + var title: String { + return L10n.Scene.Wizard.newInMastodon + } + + var description: String { + switch self { + case .multipleAccountSwitch: + return L10n.Scene.Wizard.multipleAccountSwitchIntroDescription + } + } + + func markAsRead() { + switch self { + case .multipleAccountSwitch: + UserDefaults.shared.didShowMultipleAccountSwitchWizard = true + } + } + } +} + +extension WizardViewController { + + func setup() { + assert(delegate != nil, "need set delegate before use") + + guard !items.isEmpty else { return } + + backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + backgroundView.frame = view.bounds + view.addSubview(backgroundView) + } + + func destroy() { + view.removeFromSuperview() + } + + func consume() { + guard !items.isEmpty else { + destroy() + return + } + + guard let first = items.first else { return } + guard delegate?.readyToLayoutItem(self, item: first) == true else { + pendingItem.value = first + return + } + pendingItem.value = nil + currentItem.value = nil + + let item = items.removeFirst() + perform(item: item) + } + + private func perform(item: Item) { + guard let delegate = delegate else { + assertionFailure() + return + } + + // prepare for reuse + prepareForReuse() + + // set wizard item read + item.markAsRead() + + // add spotlight + let spotlight = delegate.layoutSpotlight(self, item: item) + let maskLayer = CAShapeLayer() + // expand rect to make sure view always fill the screen when device rotate + let expandRect: CGRect = { + var rect = backgroundView.bounds + rect.size.width *= 2 + rect.size.height *= 2 + return rect + }() + let path = UIBezierPath(rect: expandRect) + path.append(spotlight) + maskLayer.fillRule = .evenOdd + maskLayer.path = path.cgPath + backgroundView.layer.mask = maskLayer + + // layout wizard card + delegate.layoutWizardCard(self, item: item) + + currentItem.value = item + } + + private func prepareForReuse() { + backgroundView.subviews.forEach { subview in + subview.removeFromSuperview() + } + backgroundView.mask = nil + backgroundView.layer.mask = nil + } + + private func invalidLayoutForCurrentItem() { + if let item = currentItem.value { + perform(item: item) + } + } + +} + +extension WizardViewController { + @objc private func backgroundTapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + + consume() + } +} From 1aea75fb830f01a3a76d90f0f435dbb03e1b6cd3 Mon Sep 17 00:00:00 2001 From: CMK Date: Tue, 2 Nov 2021 19:16:34 +0800 Subject: [PATCH 43/87] chore: update version to 1.2.0 (83) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon.xcodeproj/project.pbxproj | 64 +++++++++---------- .../xcschemes/xcschememanagement.plist | 8 +-- Mastodon/Info.plist | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 11 files changed, 45 insertions(+), 45 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 16c084cec..be737c933 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index 16c084cec..be737c933 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index 16c084cec..be737c933 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 619baa12b..a2a357c8c 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4903,7 +4903,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4932,7 +4932,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5040,11 +5040,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5071,11 +5071,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5100,11 +5100,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5130,11 +5130,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5197,7 +5197,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5222,7 +5222,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5247,7 +5247,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5272,7 +5272,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5297,7 +5297,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5322,7 +5322,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5347,7 +5347,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5372,7 +5372,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5463,7 +5463,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5530,11 +5530,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5579,7 +5579,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5604,11 +5604,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5700,7 +5700,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5767,11 +5767,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5816,7 +5816,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5841,11 +5841,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 82; + DYLIB_CURRENT_VERSION = 83; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5871,7 +5871,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5895,7 +5895,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 82; + CURRENT_PROJECT_VERSION = 83; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 5a5418919..fce311786 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 37 + 44 CoreDataStack.xcscheme_^#shared#^_ orderHint - 36 + 43 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -97,7 +97,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 35 + 41 MastodonIntents.xcscheme_^#shared#^_ @@ -117,7 +117,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 38 + 42 SuppressBuildableAutocreation diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index a75982e39..f5b56d6da 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 82 + 83 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index ed243297d..a79ce28b2 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 16c084cec..be737c933 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 16c084cec..be737c933 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index 89e562534..7f407c80d 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 79ba82cef..fd2a138c0 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 82 + 83 NSExtension NSExtensionAttributes From f6351f3c35a1adbdfdb3393ae7893590ddad9cac Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 2 Nov 2021 19:03:38 +0100 Subject: [PATCH 44/87] New translations app.json (Thai) --- Localization/StringsConvertor/input/th_TH/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/th_TH/app.json b/Localization/StringsConvertor/input/th_TH/app.json index f9e56214c..7852b5d01 100644 --- a/Localization/StringsConvertor/input/th_TH/app.json +++ b/Localization/StringsConvertor/input/th_TH/app.json @@ -67,7 +67,7 @@ "done": "เสร็จสิ้น", "confirm": "ยืนยัน", "continue": "ดำเนินการต่อ", - "compose": "Compose", + "compose": "เขียน", "cancel": "ยกเลิก", "discard": "ละทิ้ง", "try_again": "ลองอีกครั้ง", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "ไม่ได้แสดงผู้ติดตามจากเซิร์ฟเวอร์อื่น ๆ" }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "ไม่ได้แสดงการติดตามจากเซิร์ฟเวอร์อื่น ๆ" }, "search": { "title": "ค้นหา", From 716326351e5f0206b8f12c5fcfef01eaf75aabc9 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 14:24:52 +0800 Subject: [PATCH 45/87] feat: add store rating supports --- Mastodon.xcodeproj/project.pbxproj | 4 +++ .../xcschemes/xcschememanagement.plist | 8 +++--- .../Preference/StoreReviewPreference.swift | 26 +++++++++++++++++++ ...meTimelineViewController+DebugAction.swift | 6 +++++ .../HomeTimelineViewController.swift | 16 ++++++++++++ Mastodon/Service/StatusPublishService.swift | 2 +- Mastodon/Supporting Files/AppDelegate.swift | 5 ++++ 7 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 Mastodon/Preference/StoreReviewPreference.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index a2a357c8c..5e23b5786 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -321,6 +321,7 @@ 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 */; }; DB6804662636DC9000430867 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D939AB425EDD8A90076FA61 /* String.swift */; }; DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68045A2636DC6A00430867 /* MastodonNotification.swift */; }; @@ -1141,6 +1142,7 @@ DB66729B25F9F91F00D60309 /* ComposeStatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusItem.swift; sourceTree = ""; }; DB67D08327312970006A36CF /* APIService+Following.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Following.swift"; sourceTree = ""; }; DB67D08527312E67006A36CF /* WizardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardViewController.swift; sourceTree = ""; }; + DB67D088273256D7006A36CF /* StoreReviewPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreReviewPreference.swift; sourceTree = ""; }; DB68045A2636DC6A00430867 /* MastodonNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonNotification.swift; sourceTree = ""; }; 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 = ""; }; @@ -2447,6 +2449,7 @@ DB1D842F26566512000346B3 /* KeyboardPreference.swift */, DBCBCC0C2680B908000F5B51 /* HomeTimelinePreference.swift */, DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */, + DB67D088273256D7006A36CF /* StoreReviewPreference.swift */, ); path = Preference; sourceTree = ""; @@ -4101,6 +4104,7 @@ DBE3CE01261D623D00430CC6 /* FavoriteViewModel+State.swift in Sources */, 2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */, 2D38F1EB25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift in Sources */, + DB67D089273256D7006A36CF /* StoreReviewPreference.swift in Sources */, DB5B7295273112B100081888 /* FollowingListViewController.swift in Sources */, 0F202201261326E6000C64BF /* HashtagTimelineViewModel.swift in Sources */, DB6D9F9726367249008423CD /* SettingsViewController.swift in Sources */, diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index fce311786..e6093a218 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 44 + 35 CoreDataStack.xcscheme_^#shared#^_ orderHint - 43 + 38 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -97,7 +97,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 41 + 36 MastodonIntents.xcscheme_^#shared#^_ @@ -117,7 +117,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 42 + 37 SuppressBuildableAutocreation diff --git a/Mastodon/Preference/StoreReviewPreference.swift b/Mastodon/Preference/StoreReviewPreference.swift new file mode 100644 index 000000000..e3a403f6d --- /dev/null +++ b/Mastodon/Preference/StoreReviewPreference.swift @@ -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 } + } + +} diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift index 6d79d0603..6e75a17e7 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift @@ -15,6 +15,7 @@ import FLEX import SwiftUI import MastodonUI import MastodonSDK +import StoreKit extension HomeTimelineViewController { var debugMenu: UIMenu { @@ -77,6 +78,11 @@ extension HomeTimelineViewController { guard let self = self else { return } 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) + }, ] ) } diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 6b5476885..62695f211 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -14,6 +14,7 @@ import CoreDataStack import GameplayKit import MastodonSDK import AlamofireImage +import StoreKit final class HomeTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController { @@ -144,6 +145,21 @@ extension HomeTimelineViewController { } .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 refreshControl.addTarget(self, action: #selector(HomeTimelineViewController.refreshControlValueChanged(_:)), for: .valueChanged) diff --git a/Mastodon/Service/StatusPublishService.swift b/Mastodon/Service/StatusPublishService.swift index ed894f933..f5c4cb2dd 100644 --- a/Mastodon/Service/StatusPublishService.swift +++ b/Mastodon/Service/StatusPublishService.swift @@ -12,6 +12,7 @@ import Combine import CoreData import CoreDataStack import MastodonSDK +import UIKit final class StatusPublishService { @@ -72,7 +73,6 @@ extension StatusPublishService { self.viewModels.value = viewModels os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: composeViewModel removed", ((#file as NSString).lastPathComponent), #line, #function) - } } diff --git a/Mastodon/Supporting Files/AppDelegate.swift b/Mastodon/Supporting Files/AppDelegate.swift index 87d16241a..e2cb7c41b 100644 --- a/Mastodon/Supporting Files/AppDelegate.swift +++ b/Mastodon/Supporting Files/AppDelegate.swift @@ -36,6 +36,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { UNUserNotificationCenter.current().delegate = self application.registerForRemoteNotifications() + // increase app process count + var count = UserDefaults.shared.processCompletedCount + count += 1 // Int64. could ignore overflow here + UserDefaults.shared.processCompletedCount = count + #if ASDK && DEBUG // PerformanceMonitor.shared().start() // ASDisplayNode.shouldShowRangeDebugOverlay = true From bab09c36fde9a6cbaf587e842277c8bb13b6a8bb Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 15:15:55 +0800 Subject: [PATCH 46/87] fix: AutoLayout may enter infinity layout loop issue --- .../Scene/Root/Sidebar/SidebarViewController.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift index d2dae2478..b5f67e769 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift @@ -125,10 +125,16 @@ extension SidebarViewController { secondaryCollectionView.observe(\.contentSize, options: [.initial, .new]) { [weak self] secondaryCollectionView, _ in guard let self = self else { return } + + let contentHeight = secondaryCollectionView.contentSize.height + guard contentHeight > 0 else { return } self.logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): secondaryCollectionView contentSize: \(secondaryCollectionView.contentSize.debugDescription)") - let height = secondaryCollectionView.contentSize.height - self.secondaryCollectionViewHeightLayoutConstraint.constant = height - self.collectionView.contentInset.bottom = height + + let currentFrameHeight = secondaryCollectionView.frame.height + guard currentFrameHeight < contentHeight else { return } + + self.secondaryCollectionViewHeightLayoutConstraint.constant = contentHeight + self.collectionView.contentInset.bottom = contentHeight } .store(in: &observations) @@ -147,7 +153,6 @@ extension SidebarViewController { coordinator.animate { context in self.collectionView.collectionViewLayout.invalidateLayout() -// // do nothing } completion: { [weak self] context in // guard let self = self else { return } } From 757578e97e7d3c0f9439b70e9d759f5a8ff5416a Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 15:16:17 +0800 Subject: [PATCH 47/87] fix: image transitioning clip invisible tab bar issue --- ...viewViewControllerAnimatedTransitioning.swift | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift b/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift index 9fbbbd888..ec4ac35ad 100644 --- a/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift +++ b/Mastodon/Scene/Transition/MediaPreview/MediaHostToMediaPreviewViewControllerAnimatedTransitioning.swift @@ -184,9 +184,13 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning { let maskLayerToPath = maskLayerToRect.flatMap { UIBezierPath(rect: $0) }?.cgPath let maskLayerToFinalRect: CGRect? = { guard case .mosaic = transitionItem.source else { return nil } - guard let tabBarController = toVC.tabBarController, let tabBarSuperView = tabBarController.tabBar.superview else { return nil } - let tabBarFrameInWindow = tabBarSuperView.convert(tabBarController.tabBar.frame, to: nil) var rect = maskLayerToRect ?? transitionMaskView.frame + // clip tabBar when bar visible + guard let tabBarController = toVC.tabBarController, + !tabBarController.tabBar.isHidden, + let tabBarSuperView = tabBarController.tabBar.superview + else { return rect } + let tabBarFrameInWindow = tabBarSuperView.convert(tabBarController.tabBar.frame, to: nil) let offset = rect.maxY - tabBarFrameInWindow.minY guard offset > 0 else { return rect } rect.size.height -= offset @@ -473,9 +477,13 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning { let maskLayerToFinalRect: CGRect? = { guard case .mosaic = transitionItem.source else { return nil } - guard let tabBarController = toVC.tabBarController, let tabBarSuperView = tabBarController.tabBar.superview else { return nil } - let tabBarFrameInWindow = tabBarSuperView.convert(tabBarController.tabBar.frame, to: nil) var rect = maskLayerToRect ?? transitionMaskView.frame + // clip rect bottom when tabBar visible + guard let tabBarController = toVC.tabBarController, + !tabBarController.tabBar.isHidden, + let tabBarSuperView = tabBarController.tabBar.superview + else { return rect } + let tabBarFrameInWindow = tabBarSuperView.convert(tabBarController.tabBar.frame, to: nil) let offset = rect.maxY - tabBarFrameInWindow.minY guard offset > 0 else { return rect } rect.size.height -= offset From e15e373f3db4e74c1625124c3bfdd5e35590bc0f Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 15:29:25 +0800 Subject: [PATCH 48/87] fix: search controller cannot trigger become first responder issue --- Mastodon/Scene/Root/RootSplitViewController.swift | 4 ++-- .../Search/SearchDetail/SearchDetailViewController.swift | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index 2b3c858e0..f13383de6 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -307,8 +307,8 @@ extension RootSplitViewController: WizardViewControllerDelegate { let cell = contentSplitViewController.sidebarViewController.collectionView.cellForItem(at: indexPath) as? SidebarListCollectionViewCell, let contentView = cell._contentView, let frame = sourceViewFrameInTargetView( - sourceView: contentView.avatarButton, - targetView: wizardView + sourceView: contentView.avatarButton, + targetView: wizardView ) else { assertionFailure() diff --git a/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift b/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift index b401e7955..486a3b48a 100644 --- a/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift +++ b/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift @@ -245,7 +245,9 @@ extension SearchDetailViewController { searchBar.becomeFirstResponder() } else { searchController.isActive = true - searchController.searchBar.becomeFirstResponder() + DispatchQueue.main.asyncAfter(deadline: .now() + 0.33) { + self.searchController.searchBar.becomeFirstResponder() + } } } From b95dc6ad279d72b3a5ad074f987628a15bd0bfd8 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 15:31:59 +0800 Subject: [PATCH 49/87] chore: update i18n resources --- Mastodon/Resources/es.lproj/Localizable.strings | 6 +++--- Mastodon/Resources/th.lproj/Localizable.strings | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Mastodon/Resources/es.lproj/Localizable.strings b/Mastodon/Resources/es.lproj/Localizable.strings index 5e7f9afbe..dcf12dfe2 100644 --- a/Mastodon/Resources/es.lproj/Localizable.strings +++ b/Mastodon/Resources/es.lproj/Localizable.strings @@ -28,7 +28,7 @@ Por favor, revise su conexión a internet."; "Common.Controls.Actions.Back" = "Atrás"; "Common.Controls.Actions.BlockDomain" = "Bloquear %@"; "Common.Controls.Actions.Cancel" = "Cancelar"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "Redactar"; "Common.Controls.Actions.Confirm" = "Confirmar"; "Common.Controls.Actions.Continue" = "Continuar"; "Common.Controls.Actions.CopyPhoto" = "Copiar foto"; @@ -191,8 +191,8 @@ subirse a Mastodon."; pulsa en el enlace para confirmar tu cuenta."; "Scene.ConfirmEmail.Title" = "Una última cosa."; "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.Follower.Footer" = "No se muestran los seguidores de otros servidores."; +"Scene.Following.Footer" = "No se muestran los seguidos de otros servidores."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevas publicaciones"; "Scene.HomeTimeline.NavigationBarState.Offline" = "Sin Conexión"; "Scene.HomeTimeline.NavigationBarState.Published" = "¡Publicado!"; diff --git a/Mastodon/Resources/th.lproj/Localizable.strings b/Mastodon/Resources/th.lproj/Localizable.strings index d05bb5834..1bd954fe5 100644 --- a/Mastodon/Resources/th.lproj/Localizable.strings +++ b/Mastodon/Resources/th.lproj/Localizable.strings @@ -28,7 +28,7 @@ "Common.Controls.Actions.Back" = "ย้อนกลับ"; "Common.Controls.Actions.BlockDomain" = "ปิดกั้น %@"; "Common.Controls.Actions.Cancel" = "ยกเลิก"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "เขียน"; "Common.Controls.Actions.Confirm" = "ยืนยัน"; "Common.Controls.Actions.Continue" = "ดำเนินการต่อ"; "Common.Controls.Actions.CopyPhoto" = "คัดลอกรูปภาพ"; @@ -191,8 +191,8 @@ แตะที่ลิงก์เพื่อยืนยันบัญชีของคุณ"; "Scene.ConfirmEmail.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.Follower.Footer" = "ไม่ได้แสดงผู้ติดตามจากเซิร์ฟเวอร์อื่น ๆ"; +"Scene.Following.Footer" = "ไม่ได้แสดงการติดตามจากเซิร์ฟเวอร์อื่น ๆ"; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "ดูโพสต์ใหม่"; "Scene.HomeTimeline.NavigationBarState.Offline" = "ออฟไลน์"; "Scene.HomeTimeline.NavigationBarState.Published" = "เผยแพร่แล้ว!"; From a590917afdb294d37c4d61546a75715bebc43e7e Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 15:49:42 +0800 Subject: [PATCH 50/87] chore: update MetaTextKit package version to v2.1.2 to workaround SDWebImage crash issue --- Mastodon.xcodeproj/project.pbxproj | 66 +++++++++---------- .../xcschemes/xcschememanagement.plist | 34 +++++----- .../xcshareddata/swiftpm/Package.resolved | 4 +- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 5e23b5786..1c0c420dd 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4907,7 +4907,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4936,7 +4936,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5044,11 +5044,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5075,11 +5075,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5104,11 +5104,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5134,11 +5134,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5201,7 +5201,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5226,7 +5226,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5251,7 +5251,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5276,7 +5276,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5301,7 +5301,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5326,7 +5326,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5351,7 +5351,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5376,7 +5376,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5467,7 +5467,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5534,11 +5534,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5583,7 +5583,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5608,11 +5608,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5704,7 +5704,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5771,11 +5771,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5820,7 +5820,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5845,11 +5845,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 83; + DYLIB_CURRENT_VERSION = 84; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5875,7 +5875,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5899,7 +5899,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -6070,7 +6070,7 @@ repositoryURL = "https://github.com/TwidereProject/MetaTextKit.git"; requirement = { kind = exactVersion; - version = 2.1.1; + version = 2.1.2; }; }; DB0E2D2C26833FF600865C3C /* XCRemoteSwiftPackageReference "Nuke-FLAnimatedImage-Plugin" */ = { diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index e6093a218..1bf25c439 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 35 + 38 CoreDataStack.xcscheme_^#shared#^_ orderHint - 38 + 37 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -22,7 +22,7 @@ Mastodon - RTL.xcscheme_^#shared#^_ orderHint - 13 + 14 Mastodon - Release.xcscheme_^#shared#^_ @@ -32,17 +32,17 @@ Mastodon - ar.xcscheme_^#shared#^_ orderHint - 10 + 11 Mastodon - ca.xcscheme_^#shared#^_ orderHint - 16 + 17 Mastodon - de.xcscheme_^#shared#^_ orderHint - 11 + 12 Mastodon - en.xcscheme_^#shared#^_ @@ -52,42 +52,42 @@ Mastodon - es-419.xcscheme_^#shared#^_ orderHint - 8 + 9 Mastodon - es.xcscheme_^#shared#^_ orderHint - 7 + 8 Mastodon - fr.xcscheme_^#shared#^_ orderHint - 9 + 10 Mastodon - jp.xcscheme_^#shared#^_ orderHint - 14 + 15 Mastodon - nl.xcscheme_^#shared#^_ orderHint - 12 + 13 Mastodon - ru.xcscheme_^#shared#^_ orderHint - 4 + 5 Mastodon - th.xcscheme_^#shared#^_ orderHint - 5 + 6 Mastodon - zh_Hans.xcscheme_^#shared#^_ orderHint - 15 + 16 Mastodon.xcscheme_^#shared#^_ @@ -97,7 +97,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 36 + 39 MastodonIntents.xcscheme_^#shared#^_ @@ -112,12 +112,12 @@ NotificationService.xcscheme_^#shared#^_ orderHint - 6 + 7 ShareActionExtension.xcscheme_^#shared#^_ orderHint - 37 + 41 SuppressBuildableAutocreation diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index b305c8156..11dde7269 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -96,8 +96,8 @@ "repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git", "state": { "branch": null, - "revision": "a5f412b72fc08cd1348e2388fc7ec326365e1823", - "version": "2.1.1" + "revision": "7af4182f64329440a4656f2cba307cb5848e496a", + "version": "2.1.2" } }, { From 66f69ccd65b31b22a4e6f9df1b9f0fe61c0eabea Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 15:50:48 +0800 Subject: [PATCH 51/87] chore: update version to 1.2.0 (84) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon/Info.plist | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index be737c933..af3c11d9a 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index be737c933..af3c11d9a 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index be737c933..af3c11d9a 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index f5b56d6da..c5ed838f9 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 83 + 84 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index a79ce28b2..43bd255d9 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index be737c933..af3c11d9a 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index be737c933..af3c11d9a 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index 7f407c80d..7250b3468 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index fd2a138c0..262484f7b 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 83 + 84 NSExtension NSExtensionAttributes From 1338757670871abef2c4fc45eb59b3eaf1b158b5 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 16:13:11 +0800 Subject: [PATCH 52/87] chore: update gitignore rules --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 2c475f675..a605c524d 100644 --- a/.gitignore +++ b/.gitignore @@ -122,5 +122,4 @@ xcuserdata Localization/StringsConvertor/input Localization/StringsConvertor/output -.DS_Store -/Mastodon.xcworkspace/xcshareddata/swiftpm +.DS_Store \ No newline at end of file From 9dac014c7f87673cb7a0abb4b5abe0256cb400e7 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 3 Nov 2021 16:21:09 +0800 Subject: [PATCH 53/87] chore: update CI configure for Xcode 13.1 --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ea365bca9..b2979d002 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,8 +19,8 @@ jobs: steps: - name: checkout uses: actions/checkout@v2 - - name: force Xcode 13.0 - run: sudo xcode-select -switch /Applications/Xcode_13.0.app + - name: force Xcode 13.1 + run: sudo xcode-select -switch /Applications/Xcode_13.1.app - name: setup run: exec ./.github/scripts/setup.sh - name: build From 42ea3f95ca4758e29511801292b904acf08bb396 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 12:17:02 +0800 Subject: [PATCH 54/87] fix: some language issue may clip trend card label issue --- .../SearchRecommendTagsCollectionViewCell.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Mastodon/Scene/Search/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift b/Mastodon/Scene/Search/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift index 3734bc8a4..3a20788b5 100644 --- a/Mastodon/Scene/Search/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift +++ b/Mastodon/Scene/Search/Search/CollectionViewCell/SearchRecommendTagsCollectionViewCell.swift @@ -27,6 +27,7 @@ class SearchRecommendTagsCollectionViewCell: UICollectionViewCell { let label = UILabel() label.textColor = .white label.font = .preferredFont(forTextStyle: .body) + label.numberOfLines = 2 return label }() From 00cf2db8a1573ae80bd7f495b18ca14df360226a Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 14:12:22 +0800 Subject: [PATCH 55/87] chore: set sidebar logo color to app tint color --- Mastodon/Scene/Root/Sidebar/View/SidebarListHeaderView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mastodon/Scene/Root/Sidebar/View/SidebarListHeaderView.swift b/Mastodon/Scene/Root/Sidebar/View/SidebarListHeaderView.swift index 2056c5dcd..6a1bb3ddf 100644 --- a/Mastodon/Scene/Root/Sidebar/View/SidebarListHeaderView.swift +++ b/Mastodon/Scene/Root/Sidebar/View/SidebarListHeaderView.swift @@ -11,7 +11,8 @@ final class SidebarListHeaderView: UICollectionReusableView { let imageView: UIImageView = { let imageView = UIImageView() - imageView.image = Asset.Scene.Sidebar.logo.image + imageView.image = Asset.Scene.Sidebar.logo.image.withRenderingMode(.alwaysTemplate) + imageView.tintColor = .label return imageView }() From 469acd12f544c006ca299e766c30f60bb817a9a1 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 15:13:17 +0800 Subject: [PATCH 56/87] fix: account switch scene not adopt elevated color issue --- .../Scene/Account/AccountViewController.swift | 12 ++++++++-- .../Cell/AccountListTableViewCell.swift | 10 ++++++++ .../Cell/AddAccountTableViewCell.swift | 12 ++++++++++ .../MastodonRegisterViewController.swift | 4 ++-- .../Scene/Report/ReportViewController.swift | 24 +++++++++---------- .../Report/ReportedStatusTableviewCell.swift | 3 ++- 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Mastodon/Scene/Account/AccountViewController.swift b/Mastodon/Scene/Account/AccountViewController.swift index 4f2ece253..fce9c7320 100644 --- a/Mastodon/Scene/Account/AccountViewController.swift +++ b/Mastodon/Scene/Account/AccountViewController.swift @@ -75,7 +75,7 @@ extension AccountListViewController { override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = ThemeService.shared.currentTheme.value.systemBackgroundColor.withAlphaComponent(0.9) + setupBackgroundColor(theme: ThemeService.shared.currentTheme.value) ThemeService.shared.currentTheme .receive(on: DispatchQueue.main) .sink { [weak self] theme in @@ -131,7 +131,15 @@ extension AccountListViewController { } private func setupBackgroundColor(theme: Theme) { - view.backgroundColor = theme.systemBackgroundColor.withAlphaComponent(0.9) + let backgroundColor = UIColor { traitCollection in + switch traitCollection.userInterfaceLevel { + case .elevated where traitCollection.userInterfaceStyle == .dark: + return theme.systemElevatedBackgroundColor + default: + return theme.systemBackgroundColor.withAlphaComponent(0.9) + } + } + view.backgroundColor = backgroundColor } } diff --git a/Mastodon/Scene/Account/Cell/AccountListTableViewCell.swift b/Mastodon/Scene/Account/Cell/AccountListTableViewCell.swift index b8f7d5381..f6ab75877 100644 --- a/Mastodon/Scene/Account/Cell/AccountListTableViewCell.swift +++ b/Mastodon/Scene/Account/Cell/AccountListTableViewCell.swift @@ -12,6 +12,7 @@ import MetaTextKit final class AccountListTableViewCell: UITableViewCell { + private var _disposeBag = Set() var disposeBag = Set() let avatarButton = CircleAvatarButton(frame: .zero) @@ -47,6 +48,15 @@ final class AccountListTableViewCell: UITableViewCell { extension AccountListTableViewCell { private func _init() { + backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor + } + .store(in: &_disposeBag) + avatarButton.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(avatarButton) NSLayoutConstraint.activate([ diff --git a/Mastodon/Scene/Account/Cell/AddAccountTableViewCell.swift b/Mastodon/Scene/Account/Cell/AddAccountTableViewCell.swift index 722896641..0873c1390 100644 --- a/Mastodon/Scene/Account/Cell/AddAccountTableViewCell.swift +++ b/Mastodon/Scene/Account/Cell/AddAccountTableViewCell.swift @@ -6,10 +6,13 @@ // import UIKit +import Combine import MetaTextKit final class AddAccountTableViewCell: UITableViewCell { + private var _disposeBag = Set() + let iconImageView: UIImageView = { let image = UIImage(systemName: "plus.circle.fill")! let imageView = UIImageView(image: image) @@ -41,6 +44,15 @@ final class AddAccountTableViewCell: UITableViewCell { extension AddAccountTableViewCell { private func _init() { + backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor + ThemeService.shared.currentTheme + .receive(on: RunLoop.main) + .sink { [weak self] theme in + guard let self = self else { return } + self.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor + } + .store(in: &_disposeBag) + iconImageView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(iconImageView) NSLayoutConstraint.activate([ diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift index b86c46745..4cf4da14d 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift @@ -312,7 +312,7 @@ extension MastodonRegisterViewController { view.addGestureRecognizer(tapGestureRecognizer) tapGestureRecognizer.addTarget(self, action: #selector(tapGestureRecognizerHandler)) - // stackview + // stackView stackView.axis = .vertical stackView.distribution = .fill stackView.spacing = 40 @@ -370,7 +370,7 @@ extension MastodonRegisterViewController { scrollView.frameLayoutGuide.widthAnchor.constraint(equalTo: scrollView.contentLayoutGuide.widthAnchor), ]) - // stackview + // stackView scrollView.addSubview(stackView) stackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ diff --git a/Mastodon/Scene/Report/ReportViewController.swift b/Mastodon/Scene/Report/ReportViewController.swift index 6a7161c91..b97424cb5 100644 --- a/Mastodon/Scene/Report/ReportViewController.swift +++ b/Mastodon/Scene/Report/ReportViewController.swift @@ -51,7 +51,7 @@ class ReportViewController: UIViewController, NeedsDependency { return view }() - lazy var stackview: UIStackView = { + lazy var stackView: UIStackView = { let view = UIStackView() view.axis = .vertical view.alignment = .fill @@ -122,19 +122,19 @@ class ReportViewController: UIViewController, NeedsDependency { setupNavigation() - stackview.addArrangedSubview(header) - stackview.addArrangedSubview(contentView) - stackview.addArrangedSubview(footer) - stackview.addArrangedSubview(bottomSpacing) + stackView.addArrangedSubview(header) + stackView.addArrangedSubview(contentView) + stackView.addArrangedSubview(footer) + stackView.addArrangedSubview(bottomSpacing) contentView.addSubview(tableView) - view.addSubview(stackview) + view.addSubview(stackView) NSLayoutConstraint.activate([ - stackview.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - stackview.leadingAnchor.constraint(equalTo: view.leadingAnchor), - stackview.bottomAnchor.constraint(equalTo: view.bottomAnchor), - stackview.trailingAnchor.constraint(equalTo: view.trailingAnchor), + stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor), tableView.topAnchor.constraint(equalTo: contentView.topAnchor), tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), @@ -273,8 +273,8 @@ class ReportViewController: UIViewController, NeedsDependency { navigationItem.titleView = titleView if let user = beReportedUser { do { - let mastodonConent = MastodonContent(content: user.displayNameWithFallback, emojis: user.emojiMeta) - let metaContent = try MastodonMetaContent.convert(document: mastodonConent) + let mastodonContent = MastodonContent(content: user.displayNameWithFallback, emojis: user.emojiMeta) + let metaContent = try MastodonMetaContent.convert(document: mastodonContent) titleView.update(titleMetaContent: metaContent, subtitle: nil) } catch { let metaContent = PlaintextMetaContent(string: user.displayNameWithFallback) diff --git a/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift b/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift index ff566a248..0880c479a 100644 --- a/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift +++ b/Mastodon/Scene/Report/ReportedStatusTableviewCell.swift @@ -19,6 +19,7 @@ final class ReportedStatusTableViewCell: UITableViewCell, StatusCell { static let bottomPaddingHeight: CGFloat = 10 weak var dependency: ReportViewController? + private var _disposeBag = Set() var disposeBag = Set() var observations = Set() @@ -98,7 +99,7 @@ extension ReportedStatusTableViewCell { guard let self = self else { return } self.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemGroupedBackgroundColor } - .store(in: &disposeBag) + .store(in: &_disposeBag) checkbox.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(checkbox) From 0462ade3ae46e239c7c488853d65ff8ce2325082 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 15:20:37 +0800 Subject: [PATCH 57/87] fix: iPad columns separator line color not update when toggle device appearance issue --- Mastodon/Scene/Root/RootSplitViewController.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index f13383de6..505e9089d 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -109,6 +109,12 @@ extension RootSplitViewController { } } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + setupBackground(theme: ThemeService.shared.currentTheme.value) + } + private func updateBehavior(size: CGSize) { if size.width > 960 { show(.primary) @@ -136,7 +142,7 @@ extension RootSplitViewController { private func setupBackground(theme: Theme) { // this set column separator line color - view.backgroundColor = theme.separator + view.backgroundColor = .opaqueSeparator } } From 1cbc38525395fd9fc51d9ba4e80281d102dd5a1e Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 15:21:12 +0800 Subject: [PATCH 58/87] fix: sidebar avatar button color not update when toggle device appearance issue --- .../Root/Sidebar/View/SidebarListContentView.swift | 2 +- Mastodon/Scene/Share/View/Button/AvatarButton.swift | 12 ++++++++++++ .../Scene/Share/View/Button/CircleAvatarButton.swift | 11 +++++++---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Mastodon/Scene/Root/Sidebar/View/SidebarListContentView.swift b/Mastodon/Scene/Root/Sidebar/View/SidebarListContentView.swift index d85d3a8be..d6ae40e17 100644 --- a/Mastodon/Scene/Root/Sidebar/View/SidebarListContentView.swift +++ b/Mastodon/Scene/Root/Sidebar/View/SidebarListContentView.swift @@ -18,7 +18,7 @@ final class SidebarListContentView: UIView, UIContentView { let avatarButton: CircleAvatarButton = { let button = CircleAvatarButton() button.borderWidth = 2 - button.borderColor = UIColor.label.cgColor + button.borderColor = UIColor.label return button }() diff --git a/Mastodon/Scene/Share/View/Button/AvatarButton.swift b/Mastodon/Scene/Share/View/Button/AvatarButton.swift index 9bc87a053..6249ea373 100644 --- a/Mastodon/Scene/Share/View/Button/AvatarButton.swift +++ b/Mastodon/Scene/Share/View/Button/AvatarButton.swift @@ -38,6 +38,18 @@ class AvatarButton: UIControl { avatarImageView.bottomAnchor.constraint(equalTo: bottomAnchor), ]) } + + override func layoutSubviews() { + super.layoutSubviews() + + updateAppearance() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + updateAppearance() + } func updateAppearance() { avatarImageView.alpha = primaryActionState.contains(.highlighted) ? 0.6 : 1.0 diff --git a/Mastodon/Scene/Share/View/Button/CircleAvatarButton.swift b/Mastodon/Scene/Share/View/Button/CircleAvatarButton.swift index 0bc2aeefd..74591dda9 100644 --- a/Mastodon/Scene/Share/View/Button/CircleAvatarButton.swift +++ b/Mastodon/Scene/Share/View/Button/CircleAvatarButton.swift @@ -9,15 +9,18 @@ import UIKit final class CircleAvatarButton: AvatarButton { - var borderColor: CGColor = UIColor.systemFill.cgColor + @Published var needsHighlighted = false + + var borderColor: UIColor = UIColor.systemFill var borderWidth: CGFloat = 1.0 - override func layoutSubviews() { - super.layoutSubviews() + override func updateAppearance() { + super.updateAppearance() layer.masksToBounds = true layer.cornerRadius = frame.width * 0.5 - layer.borderColor = borderColor + layer.borderColor = borderColor.cgColor layer.borderWidth = borderWidth } + } From 868e86e0776a0fa40e39186a18cc6c4ab452e8af Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 16:24:42 +0800 Subject: [PATCH 59/87] feat: make tabBar avatar button border highlighted when selected --- .../Scene/Root/MainTab/MainTabBarController.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index 2cb964277..8688a8fab 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -252,6 +252,14 @@ extension MainTabBarController { tabBarLongPressGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarLongPressGestureRecognizerHandler(_:))) tabBar.addGestureRecognizer(tabBarLongPressGestureRecognizer) + currentTab + .receive(on: DispatchQueue.main) + .sink { [weak self] tab in + guard let self = self else { return } + self.updateAvatarButtonAppearance() + } + .store(in: &disposeBag) + updateTabBarDisplay() #if DEBUG @@ -269,6 +277,7 @@ extension MainTabBarController { super.traitCollectionDidChange(previousTraitCollection) updateTabBarDisplay() + updateAvatarButtonAppearance() } } @@ -340,6 +349,11 @@ extension MainTabBarController { self.avatarButton.setContentHuggingPriority(.required - 1, for: .vertical) self.avatarButton.isUserInteractionEnabled = false } + + private func updateAvatarButtonAppearance() { + avatarButton.borderColor = currentTab.value == .me ? .label : .systemFill + avatarButton.setNeedsLayout() + } } extension MainTabBarController { From 29e3d10e9737f4b34691ba9eeb4b15c79af84dc2 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 19:22:51 +0800 Subject: [PATCH 60/87] fix: wizard display before sign-in at the first time install issue --- .../Root/MainTab/MainTabBarController.swift | 14 ++++++----- .../Scene/Root/Sidebar/SidebarViewModel.swift | 24 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index 8688a8fab..4b803bc49 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -252,6 +252,14 @@ extension MainTabBarController { tabBarLongPressGestureRecognizer.addTarget(self, action: #selector(MainTabBarController.tabBarLongPressGestureRecognizerHandler(_:))) tabBar.addGestureRecognizer(tabBarLongPressGestureRecognizer) + context.authenticationService.activeMastodonAuthenticationBox + .receive(on: DispatchQueue.main) + .sink { [weak self] authenticationBox in + guard let self = self else { return } + self.isReadyForWizardAvatarButton = authenticationBox != nil + } + .store(in: &disposeBag) + currentTab .receive(on: DispatchQueue.main) .sink { [weak self] tab in @@ -267,12 +275,6 @@ extension MainTabBarController { #endif } - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - isReadyForWizardAvatarButton = true - } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift index 1f982429e..5ababf161 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift @@ -18,32 +18,36 @@ final class SidebarViewModel { // input let context: AppContext - let searchHistoryFetchedResultController: SearchHistoryFetchedResultController - + @Published private var isSidebarDataSourceReady = false + @Published private var isAvatarButtonDataReady = false + // output var diffableDataSource: UICollectionViewDiffableDataSource? var secondaryDiffableDataSource: UICollectionViewDiffableDataSource? - private(set) var isReadyForWizardAvatarButton = false + @Published private(set) var isReadyForWizardAvatarButton = false let activeMastodonAuthenticationObjectID = CurrentValueSubject(nil) init(context: AppContext) { self.context = context - self.searchHistoryFetchedResultController = SearchHistoryFetchedResultController(managedObjectContext: context.managedObjectContext) + + Publishers.CombineLatest( + $isSidebarDataSourceReady, + $isAvatarButtonDataReady + ) + .map { $0 && $1 } + .assign(to: &$isReadyForWizardAvatarButton) context.authenticationService.activeMastodonAuthentication .sink { [weak self] authentication in guard let self = self else { return } - // bind search history - self.searchHistoryFetchedResultController.domain.value = authentication?.domain - self.searchHistoryFetchedResultController.userID.value = authentication?.userID // bind objectID self.activeMastodonAuthenticationObjectID.value = authentication?.objectID + + self.isAvatarButtonDataReady = authentication != nil } .store(in: &disposeBag) - - try? searchHistoryFetchedResultController.fetchedResultsController.performFetch() } } @@ -175,7 +179,7 @@ extension SidebarViewModel { // otherwise the UI layout will infinity loop _diffableDataSource.apply(sectionSnapshot, to: .main, animatingDifferences: true) { [weak self] in guard let self = self else { return } - self.isReadyForWizardAvatarButton = true + self.isSidebarDataSourceReady = true } // secondary From cd9d7982bccf61f0f2430b916bce5298204d7456 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 19:24:06 +0800 Subject: [PATCH 61/87] chore: display illustration in welcome scene --- .../xcschemes/xcschememanagement.plist | 19 +++-- .../MastodonRegisterViewController.swift | 71 ++++++++++++++++--- .../OnboardingViewControllerAppearance.swift | 6 +- 3 files changed, 77 insertions(+), 19 deletions(-) diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 1bf25c439..921a52196 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,17 +7,17 @@ AppShared.xcscheme_^#shared#^_ orderHint - 38 + 36 CoreDataStack.xcscheme_^#shared#^_ orderHint - 37 + 38 Mastodon - ASDK.xcscheme_^#shared#^_ orderHint - 3 + 4 Mastodon - RTL.xcscheme_^#shared#^_ @@ -27,7 +27,7 @@ Mastodon - Release.xcscheme_^#shared#^_ orderHint - 2 + 3 Mastodon - ar.xcscheme_^#shared#^_ @@ -37,18 +37,23 @@ Mastodon - ca.xcscheme_^#shared#^_ orderHint - 17 + 18 Mastodon - de.xcscheme_^#shared#^_ orderHint 12 - Mastodon - en.xcscheme_^#shared#^_ + Mastodon - double length.xcscheme_^#shared#^_ orderHint 1 + Mastodon - en.xcscheme_^#shared#^_ + + orderHint + 2 + Mastodon - es-419.xcscheme_^#shared#^_ orderHint @@ -117,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 41 + 37 SuppressBuildableAutocreation diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift index 4cf4da14d..8428aaa79 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift @@ -802,23 +802,48 @@ extension MastodonRegisterViewController { let password = viewModel.password.value let locale: String = { - let fallbackLanguageCode = Locale.current.languageCode ?? "en" + guard let url = Bundle.main.url(forResource: "local-codes", withExtension: "json"), + let data = try? Data(contentsOf: url), + let localCode = try? JSONDecoder().decode(MastodonLocalCode.self, from: data) + else { + assertionFailure() + return "en" + } + let fallbackLanguageCode: String = { + let code = Locale.current.languageCode ?? "en" + guard localCode[code] != nil else { return "en" } + return code + }() + + // pick device preferred language guard let identifier = Locale.preferredLanguages.first else { return fallbackLanguageCode } + // prepare languageCode and validate then return fallback if needs let local = Locale(identifier: identifier) - guard let languageCode = local.languageCode else { + guard let languageCode = local.languageCode, + localCode[languageCode] != nil + else { return fallbackLanguageCode } - switch languageCode { - case "zh": - // Check Simplified Chinese / Traditional Chinese - // https://github.com/gunchleoc/mastodon/blob/ed6153b8f24d3a8f5a124cc95683bd1f20aec882/app/helpers/settings_helper.rb - guard let regionCode = local.regionCode else { return languageCode } - return "zh" + "-" + regionCode - default: + // prepare extendCode and validate then return fallback if needs + let extendCodes: [String] = { + let locales = Locale.preferredLanguages.map { Locale(identifier: $0) } + return locales.compactMap { locale in + guard let languageCode = locale.languageCode, + let regionCode = locale.regionCode + else { return nil } + return languageCode + "-" + regionCode + } + }() + let _firstMatchExtendCode = extendCodes.first { code in + localCode[code] != nil + } + guard let firstMatchExtendCode = _firstMatchExtendCode else { return languageCode } + return firstMatchExtendCode + }() let query = Mastodon.API.Account.RegisterQuery( reason: viewModel.reason.value, @@ -828,6 +853,8 @@ extension MastodonRegisterViewController { agreement: true, // user confirmed in the server rules scene locale: locale ) + + var retryCount = 0 // register without show server rules context.apiService.accountRegister( @@ -835,6 +862,32 @@ extension MastodonRegisterViewController { query: query, authorization: viewModel.applicationAuthorization ) + .tryCatch { [weak self] error -> AnyPublisher, Error> in + guard let self = self else { throw error } + guard let error = self.viewModel.error.value as? Mastodon.API.Error, + case let .generic(errorEntity) = error.mastodonError, + errorEntity.error == "Validation failed: Locale is not included in the list" + else { + throw error + } + guard retryCount == 0 else { + throw error + } + let retryQuery = Mastodon.API.Account.RegisterQuery( + reason: query.reason, + username: query.username, + email: query.email, + password: query.password, + agreement: query.agreement, + locale: self.viewModel.instance.languages?.first ?? "en" + ) + retryCount += 1 + return self.context.apiService.accountRegister( + domain: self.viewModel.domain, + query: retryQuery, + authorization: self.viewModel.applicationAuthorization + ) + } .receive(on: DispatchQueue.main) .sink { [weak self] completion in guard let self = self else { return } diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift index 4a4d04bf6..17c4699ec 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift @@ -80,8 +80,8 @@ extension OnboardingViewControllerAppearance { extension OnboardingViewControllerAppearance { static var viewEdgeMargin: CGFloat { guard UIDevice.current.userInterfaceIdiom == .pad else { return .zero } - - let shortEdgeWidth = min(UIScreen.main.bounds.height, UIScreen.main.bounds.width) - return shortEdgeWidth * 0.17 // magic + return 20 +// let shortEdgeWidth = min(UIScreen.main.bounds.height, UIScreen.main.bounds.width) +// return shortEdgeWidth * 0.17 // magic } } From 6117c903f14508c7c7ef79e88a7ba42d3eb0b0f3 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 19:24:46 +0800 Subject: [PATCH 62/87] fix: register may fail due to locale parameter issue --- Mastodon.xcodeproj/project.pbxproj | 8 + Mastodon/Helper/MastodonLocalCode.swift | 12 ++ Mastodon/Resources/local-codes.json | 80 ++++++++ .../Welcome/WelcomeViewController.swift | 191 ++++++++++-------- 4 files changed, 202 insertions(+), 89 deletions(-) create mode 100644 Mastodon/Helper/MastodonLocalCode.swift create mode 100644 Mastodon/Resources/local-codes.json diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 1c0c420dd..a1fec6337 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -607,6 +607,8 @@ DBF1D24E269DAF5D00C1C08A /* SearchDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF1D24D269DAF5D00C1C08A /* SearchDetailViewController.swift */; }; DBF1D251269DB01200C1C08A /* SearchHistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF1D250269DB01200C1C08A /* SearchHistoryViewController.swift */; }; DBF1D257269DBAC600C1C08A /* SearchDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF1D256269DBAC600C1C08A /* SearchDetailViewModel.swift */; }; + DBF3B73F2733EAED00E21627 /* local-codes.json in Resources */ = {isa = PBXBuildFile; fileRef = DBF3B73E2733EAED00E21627 /* local-codes.json */; }; + DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */; }; DBF7A0FC26830C33004176A2 /* FPSIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = DBF7A0FB26830C33004176A2 /* FPSIndicator */; }; DBF8AE16263293E400C9C23C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF8AE15263293E400C9C23C /* NotificationService.swift */; }; DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DBF8AE13263293E400C9C23C /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -1426,6 +1428,8 @@ DBF1D24D269DAF5D00C1C08A /* SearchDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchDetailViewController.swift; sourceTree = ""; }; DBF1D250269DB01200C1C08A /* SearchHistoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHistoryViewController.swift; sourceTree = ""; }; DBF1D256269DBAC600C1C08A /* SearchDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchDetailViewModel.swift; sourceTree = ""; }; + DBF3B73E2733EAED00E21627 /* local-codes.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "local-codes.json"; sourceTree = ""; }; + DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLocalCode.swift; sourceTree = ""; }; DBF53F5F25C14E88008AAC7B /* Mastodon.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = Mastodon.xctestplan; path = Mastodon/Mastodon.xctestplan; sourceTree = ""; }; DBF53F6025C14E9D008AAC7B /* MastodonSDK.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MastodonSDK.xctestplan; sourceTree = ""; }; DBF8AE13263293E400C9C23C /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2212,6 +2216,7 @@ isa = PBXGroup; children = ( 164F0EBB267D4FE400249499 /* BoopSound.caf */, + DBF3B73E2733EAED00E21627 /* local-codes.json */, DB427DDE25BAA00100D1B89D /* Assets.xcassets */, DB118A8125E4B6E600FAB162 /* Preview Assets.xcassets */, DB564BCE269F2F83001E39A7 /* Localizable.stringsdict */, @@ -3146,6 +3151,7 @@ DBBC24D626A54BCB00398BB9 /* MastodonRegex.swift */, DBBC24D826A54BCB00398BB9 /* MastodonMetricFormatter.swift */, DBFEF07626A691FB006D7ED1 /* MastodonAuthenticationBox.swift */, + DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */, ); path = Helper; sourceTree = ""; @@ -3663,6 +3669,7 @@ DB427DDF25BAA00100D1B89D /* Assets.xcassets in Resources */, DB427DDD25BAA00100D1B89D /* Main.storyboard in Resources */, DBA4B0F626C269880077136E /* Intents.stringsdict in Resources */, + DBF3B73F2733EAED00E21627 /* local-codes.json in Resources */, DB118A8225E4B6E600FAB162 /* Preview Assets.xcassets in Resources */, DB2B3ABC25E37E15007045F9 /* InfoPlist.strings in Resources */, DB68A05D25E9055900CFDF14 /* Settings.bundle in Resources */, @@ -4400,6 +4407,7 @@ 2D38F1FE25CD481700561493 /* StatusProvider.swift in Sources */, DB1EE7B2267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift in Sources */, 5B24BBE2262DB19100A9381B /* APIService+Report.swift in Sources */, + DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */, DB4F096A269EDAD200D62E92 /* SearchResultViewModel+State.swift in Sources */, 5BB04FF5262F0E6D0043BFF6 /* ReportSection.swift in Sources */, DBA94436265CBB7400C537E1 /* ProfileFieldItem.swift in Sources */, diff --git a/Mastodon/Helper/MastodonLocalCode.swift b/Mastodon/Helper/MastodonLocalCode.swift new file mode 100644 index 000000000..65d71895e --- /dev/null +++ b/Mastodon/Helper/MastodonLocalCode.swift @@ -0,0 +1,12 @@ +// +// MastodonLocalCode.swift +// Mastodon +// +// Created by Cirno MainasuK on 2021-11-4. +// + +import Foundation + +// https://github.com/gunchleoc/mastodon/blob/ed6153b8f24d3a8f5a124cc95683bd1f20aec882/app/helpers/settings_helper.rb +// last update 2021/11/4 +typealias MastodonLocalCode = [String: String] diff --git a/Mastodon/Resources/local-codes.json b/Mastodon/Resources/local-codes.json new file mode 100644 index 000000000..949649791 --- /dev/null +++ b/Mastodon/Resources/local-codes.json @@ -0,0 +1,80 @@ +{ + "af": "Afrikaans", + "ar": "العربية", + "ast": "Asturianu", + "bg": "Български", + "bn": "বাংলা", + "br": "Breton", + "ca": "Català", + "co": "Corsu", + "cs": "Čeština", + "cy": "Cymraeg", + "da": "Dansk", + "de": "Deutsch", + "el": "Ελληνικά", + "en": "English", + "eo": "Esperanto", + "es-AR": "Español (Argentina)", + "es": "Español", + "et": "Eesti", + "eu": "Euskara", + "fa": "فارسی", + "fi": "Suomi", + "fr": "Français", + "ga": "Gaeilge", + "gd": "Gàidhlig", + "gl": "Galego", + "he": "עברית", + "hi": "हिन्दी", + "hr": "Hrvatski", + "hu": "Magyar", + "hy": "Հայերեն", + "id": "Bahasa Indonesia", + "io": "Ido", + "is": "Íslenska", + "it": "Italiano", + "ja": "日本語", + "ka": "ქართული", + "kab": "Taqbaylit", + "kk": "Қазақша", + "kn": "ಕನ್ನಡ", + "ko": "한국어", + "ku": "سۆرانی", + "lt": "Lietuvių", + "lv": "Latviešu", + "mk": "Македонски", + "ml": "മലയാളം", + "mr": "मराठी", + "ms": "Bahasa Melayu", + "nl": "Nederlands", + "nn": "Nynorsk", + "no": "Norsk", + "oc": "Occitan", + "pl": "Polski", + "pt-BR": "Português (Brasil)", + "pt-PT": "Português (Portugal)", + "pt": "Português", + "ro": "Română", + "ru": "Русский", + "sa": "संस्कृतम्", + "sc": "Sardu", + "si": "සිංහල", + "sk": "Slovenčina", + "sl": "Slovenščina", + "sq": "Shqip", + "sr-Latn": "Srpski (latinica)", + "sr": "Српски", + "sv": "Svenska", + "ta": "தமிழ்", + "te": "తెలుగు", + "th": "ไทย", + "tr": "Türkçe", + "uk": "Українська", + "ur": "اُردُو", + "vi": "Tiếng Việt", + "zgh": "ⵜⴰⵎⴰⵣⵉⵖⵜ", + "zh-CN": "简体中文", + "zh-HK": "繁體中文(香港)", + "zh-TW": "繁體中文(臺灣)", + "zh": "中文" +} \ No newline at end of file diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index a2a266f9d..bf33ea13d 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -15,6 +15,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } var disposeBag = Set() + var observations = Set() private(set) lazy var viewModel = WelcomeViewModel(context: context) let welcomeIllustrationView = WelcomeIllustrationView() @@ -23,7 +24,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:))) private(set) lazy var logoImageView: UIImageView = { - let image = view.traitCollection.userInterfaceIdiom == .phone ? Asset.Scene.Welcome.mastodonLogo.image : Asset.Scene.Welcome.mastodonLogoBlackLarge.image + let image = Asset.Scene.Welcome.mastodonLogo.image let imageView = UIImageView(image: image) imageView.translatesAutoresizingMaskIntoConstraints = false return imageView @@ -40,15 +41,15 @@ final class WelcomeViewController: UIViewController, NeedsDependency { return label }() - private(set) lazy var signUpButton: PrimaryActionButton = { + private(set) lazy var signUpButton: PrimaryActionButton = { let button = PrimaryActionButton() button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false button.setTitle(L10n.Common.Controls.Actions.signUp, for: .normal) - let backgroundImageColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? .white : Asset.Colors.brandBlue.color - let backgroundImageHighlightedColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? UIColor(white: 0.8, alpha: 1.0) : Asset.Colors.brandBlueDarken20.color + let backgroundImageColor: UIColor = .white + let backgroundImageHighlightedColor: UIColor = UIColor(white: 0.8, alpha: 1.0) button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted) - let titleColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? Asset.Colors.brandBlue.color : UIColor.white + let titleColor: UIColor = Asset.Colors.brandBlue.color button.setTitleColor(titleColor, for: .normal) button.translatesAutoresizingMaskIntoConstraints = false return button @@ -58,7 +59,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { let button = UIButton(type: .system) button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)) button.setTitle(L10n.Common.Controls.Actions.signIn, for: .normal) - let titleColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? UIColor.white.withAlphaComponent(0.8) : Asset.Colors.brandBlue.color + let titleColor: UIColor = UIColor.white.withAlphaComponent(0.8) button.setTitleColor(titleColor, for: .normal) button.translatesAutoresizingMaskIntoConstraints = false return button @@ -75,6 +76,8 @@ extension WelcomeViewController { override func viewDidLoad() { super.viewDidLoad() + // preferredContentSize = CGSize(width: 547, height: 678) + navigationController?.navigationBar.prefersLargeTitles = true navigationItem.largeTitleDisplayMode = .never view.overrideUserInterfaceStyle = .light @@ -106,16 +109,31 @@ extension WelcomeViewController { self.navigationItem.leftBarButtonItem = needsShowDismissEntry ? self.dismissBarButtonItem : nil } .store(in: &disposeBag) + + view.observe(\.frame, options: [.initial, .new]) { [weak self] view, _ in + guard let self = self else { return } + switch view.traitCollection.userInterfaceIdiom { + case .phone: + break + default: + self.welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.isHidden = view.frame.height < 800 + } + } + .store(in: &observations) } override func viewSafeAreaInsetsDidChange() { super.viewSafeAreaInsetsDidChange() - // shift illustration down for non-notch phone var overlap: CGFloat = 5 + // shift illustration down for non-notch phone if view.safeAreaInsets.bottom == 0 { overlap += 56 } + // shift illustration down for iPad modal + if UIDevice.current.userInterfaceIdiom != .phone { + overlap += 20 + } welcomeIllustrationViewBottomAnchorLayoutConstraint?.constant = overlap } @@ -137,85 +155,80 @@ extension WelcomeViewController { } // set illustration for phone - if traitCollection.userInterfaceIdiom == .phone { - guard welcomeIllustrationView.superview == nil else { - return - } - - welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false - welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5) - - view.addSubview(welcomeIllustrationView) - NSLayoutConstraint.activate([ - view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15), - welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15), - welcomeIllustrationViewBottomAnchorLayoutConstraint! - ]) - - welcomeIllustrationView.cloudBaseImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5) - ) - welcomeIllustrationView.rightHillImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10) - ) - welcomeIllustrationView.leftHillImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15) - ) - welcomeIllustrationView.centerHillImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25) - ) - - let topPaddingView = UIView() - topPaddingView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(topPaddingView) - NSLayoutConstraint.activate([ - topPaddingView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor), - topPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor), - topPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor), - ]) - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(welcomeIllustrationView.elephantOnAirplaneWithContrailImageView) - NSLayoutConstraint.activate([ - view.leftAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 12), // add 12pt bleeding - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor), - // make a little bit large - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.84), - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.heightAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor, multiplier: 105.0/318.0), - ]) - let bottomPaddingView = UIView() - bottomPaddingView.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(bottomPaddingView) - NSLayoutConstraint.activate([ - bottomPaddingView.topAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.bottomAnchor), - bottomPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor), - bottomPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor), - bottomPaddingView.bottomAnchor.constraint(equalTo: view.centerYAnchor), - bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 4), - ]) - - welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.addMotionEffect( - UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt) - ) - - view.bringSubviewToFront(logoImageView) - view.bringSubviewToFront(sloganLabel) - } - - // set slogan for non-phone - if traitCollection.userInterfaceIdiom != .phone { - guard sloganLabel.superview == nil else { - return - } - view.addSubview(sloganLabel) - NSLayoutConstraint.activate([ - sloganLabel.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 16), - view.readableContentGuide.trailingAnchor.constraint(equalTo: sloganLabel.trailingAnchor, constant: 16), - sloganLabel.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 168), - ]) + guard welcomeIllustrationView.superview == nil else { + return } - view.bringSubviewToFront(sloganLabel) + welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false + welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5) + + view.addSubview(welcomeIllustrationView) + NSLayoutConstraint.activate([ + view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15), + welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15), + welcomeIllustrationViewBottomAnchorLayoutConstraint! + ]) + + welcomeIllustrationView.cloudBaseImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5) + ) + welcomeIllustrationView.rightHillImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10) + ) + welcomeIllustrationView.leftHillImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15) + ) + welcomeIllustrationView.centerHillImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25) + ) + + let topPaddingView = UIView() + topPaddingView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(topPaddingView) + NSLayoutConstraint.activate([ + topPaddingView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor), + topPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor), + topPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor), + ]) + welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(welcomeIllustrationView.elephantOnAirplaneWithContrailImageView) + NSLayoutConstraint.activate([ + view.leftAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 12), // add 12pt bleeding + welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor), + // make a little bit large + welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.84), + welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.heightAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor, multiplier: 105.0/318.0), + ]) + let bottomPaddingView = UIView() + bottomPaddingView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(bottomPaddingView) + NSLayoutConstraint.activate([ + bottomPaddingView.topAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.bottomAnchor), + bottomPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor), + bottomPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor), + bottomPaddingView.bottomAnchor.constraint(equalTo: view.centerYAnchor), + bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 4), + ]) + + welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.addMotionEffect( + UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt) + ) + view.bringSubviewToFront(logoImageView) + view.bringSubviewToFront(sloganLabel) + + // set slogan for non-phone +// if traitCollection.userInterfaceIdiom != .phone { +// guard sloganLabel.superview == nil else { +// return +// } +// view.addSubview(sloganLabel) +// NSLayoutConstraint.activate([ +// sloganLabel.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 16), +// view.readableContentGuide.trailingAnchor.constraint(equalTo: sloganLabel.trailingAnchor, constant: 16), +// sloganLabel.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 168), +// ]) +// } } } @@ -261,12 +274,12 @@ extension WelcomeViewController: UIAdaptivePresentationControllerDelegate { // make underneath view controller alive to fix layout issue due to view life cycle return .fullScreen default: - switch traitCollection.horizontalSizeClass { - case .regular: - return .pageSheet - default: - return .fullScreen - } + return .formSheet +// switch traitCollection.horizontalSizeClass { +// case .regular: +// default: +// return .fullScreen +// } } } From dd118023b96eb172554f24685e84ebc0c75cdbc6 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 4 Nov 2021 19:26:01 +0800 Subject: [PATCH 63/87] chore: update version to 1.2.0 (85) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon.xcodeproj/project.pbxproj | 64 +++++++++---------- .../xcschemes/xcschememanagement.plist | 8 +-- Mastodon/Info.plist | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 11 files changed, 45 insertions(+), 45 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index af3c11d9a..5e09203d5 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index af3c11d9a..5e09203d5 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index af3c11d9a..5e09203d5 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index a1fec6337..bad59c2b5 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4915,7 +4915,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4944,7 +4944,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5052,11 +5052,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5083,11 +5083,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5112,11 +5112,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5142,11 +5142,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5209,7 +5209,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5234,7 +5234,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5259,7 +5259,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5284,7 +5284,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5309,7 +5309,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5334,7 +5334,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5359,7 +5359,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5384,7 +5384,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5475,7 +5475,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5542,11 +5542,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5591,7 +5591,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5616,11 +5616,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5712,7 +5712,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5779,11 +5779,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5828,7 +5828,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5853,11 +5853,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 84; + DYLIB_CURRENT_VERSION = 85; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5883,7 +5883,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5907,7 +5907,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 84; + CURRENT_PROJECT_VERSION = 85; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 921a52196..7aa368605 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 36 + 42 CoreDataStack.xcscheme_^#shared#^_ orderHint - 38 + 43 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 39 + 45 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 37 + 44 SuppressBuildableAutocreation diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index c5ed838f9..d788a77cb 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 84 + 85 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index 43bd255d9..ac52ba389 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index af3c11d9a..5e09203d5 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index af3c11d9a..5e09203d5 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index 7250b3468..ae1666ce1 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 262484f7b..1b8fa72ce 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 84 + 85 NSExtension NSExtensionAttributes From 2c52c01fb76bcd05476b9c6fe0a3085d9ec108c1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 6 Nov 2021 13:05:51 +0100 Subject: [PATCH 64/87] New translations app.json (Spanish, Argentina) --- Localization/StringsConvertor/input/es_AR/app.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/es_AR/app.json b/Localization/StringsConvertor/input/es_AR/app.json index c0c884e24..ed909ecf1 100644 --- a/Localization/StringsConvertor/input/es_AR/app.json +++ b/Localization/StringsConvertor/input/es_AR/app.json @@ -67,7 +67,7 @@ "done": "Listo", "confirm": "Confirmar", "continue": "Continuar", - "compose": "Compose", + "compose": "Redactar", "cancel": "Cancelar", "discard": "Descartar", "try_again": "Intentá de nuevo", @@ -415,10 +415,10 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "No se muestran los seguidores de otros servidores." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "No se muestran las cuentas de otros servidores que seguís." }, "search": { "title": "Buscar", From 2b9f03013736ddbb5459c903f627653cb404be19 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 8 Nov 2021 11:34:36 +0100 Subject: [PATCH 65/87] New translations app.json (Kurmanji (Kurdish)) --- .../StringsConvertor/input/kmr_TR/app.json | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index 7534aede0..c3666dc60 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -16,8 +16,8 @@ "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." + "title": "Reşnivîsê paşguh bike", + "message": "Bipejrîne ku naveroka şandiyê ya hatiye nivîsandin paşguh bikî." }, "publish_post_failure": { "title": "Weşandin têkçû", @@ -28,7 +28,7 @@ } }, "edit_profile_failure": { - "title": "Çewtiya profîlê biguherîne", + "title": "Di serrastkirina profîlê çewtî", "message": "Nikare profîlê serrast bike. Jkx dîsa biceribîne." }, "sign_out": { @@ -42,15 +42,15 @@ }, "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." + "message": "Ji kerema xwe mafê bide gihîştina wênegehê çalak bike da ku wêne werin tomarkirin." }, "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." + "title": "Pêşbîrê pak bike", + "message": "Pêşbîra %s biserketî hate pakkirin." } }, "controls": { @@ -72,8 +72,8 @@ "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", + "save_photo": "Wêneyê tomar bike", + "copy_photo": "Wêneyê jê bigire", "sign_in": "Têkeve", "sign_up": "Tomar bibe", "see_more": "Bêtir bibîne", @@ -82,8 +82,8 @@ "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", + "find_people": "Mirovan bo şopandinê bibîne", + "manually_search": "Ji devlê bi destan lêgerînê bike", "skip": "Derbas bike", "reply": "Bersivê bide", "report_user": "%s ragihîne", @@ -113,47 +113,47 @@ "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ê" + "toggle_favorite": "Li ser şandiyê bijarte biguherîne", + "toggle_content_warning": "Hişyariya naverokê biguherîne", + "preview_image": "Pêşdîtina wêneyê" }, "segmented_control": { - "previous_section": "Beşa berê", - "next_section": "Beşa paşê" + "previous_section": "Beşa paş", + "next_section": "Beşa pêş" } }, "status": { - "user_reblogged": "%s ji nû ve hat blogkirin", + "user_reblogged": "%s ji nû ve hate nivîsandin", "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", + "media_content_warning": "Ji bo eşkerekirinê li derekî bitikîne", "poll": { - "vote": "Deng", + "vote": "Deng bide", "closed": "Girtî" }, "actions": { "reply": "Bersivê bide", - "reblog": "Ji nû ve blog", - "unreblog": "Ji nû ve blogkirin betal bikin", - "favorite": "Bijartî", - "unfavorite": "Nebijare", - "menu": "Menû" + "reblog": "Ji nû ve nivîsandin", + "unreblog": "Ji nû ve nivîsandinê vegere", + "favorite": "Bijarte", + "unfavorite": "Nebijarte", + "menu": "Kulîn" }, "tag": { "url": "URL", - "mention": "Behs", + "mention": "Qalkirin", "link": "Girêdan", - "hashtag": "Etîket", + "hashtag": "Hashtag", "email": "E-name", - "emoji": "E-name" + "emoji": "Emojî" } }, "friendship": { "follow": "Bişopîne", "following": "Dişopîne", - "request": "Daxwazên şopandinê", + "request": "Daxwaz bike", "pending": "Tê nirxandin", "block": "Asteng bike", "block_user": "%s asteng bike", @@ -174,18 +174,18 @@ "now": "Niha" }, "loader": { - "load_missing_posts": "Barkirina posteyên kêm", - "loading_missing_posts": "Barkirina posteyên kêm...", + "load_missing_posts": "Şandiyên wendayî bar bike", + "loading_missing_posts": "Şandiyên wendayî tên barkirin...", "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.", + "no_status_found": "Tu şandî nehate dîtin", + "blocking_warning": "Tu nikarî profîla vî/ê bikarhênerî bibînî\nHeya ku tu astengiyê li ser wî/ê ranekî.\nProfîla te ji wan ra wiha xuya dike.", + "user_blocking_warning": "Tu nikarî profîla %s bibînî\nHeya ku tu astengiyê li ser wî/ê ranekî.\nProfîla te ji wan ra wiha xuya dike.", + "blocked_warning": "Tu nikarî profîla vî/ê bikarhênerî bibînî\nheya ku ew astengiyê li ser 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." + "suspended_warning": "Ev bikarhêner hatiye rawestandin.", + "user_suspended_warning": "Ajimêra %s hatiye rawestandin." } } } @@ -219,15 +219,15 @@ "label": { "language": "ZIMAN", "users": "BIKARHÊNER", - "category": "KATEGORÎ" + "category": "BEŞ" }, "input": { - "placeholder": "Serverek bibînin an jî beşdarî ya xwe bibin..." + "placeholder": "Rajekarekî bibîne an jî beşdarî ya xwe bibe..." }, "empty_state": { - "finding_servers": "Dîtina serverên berdest...", + "finding_servers": "Peydakirina rajekarên berdest...", "bad_network": "Di dema barkirina daneyan da tiştek xelet derket. Girêdana xwe ya înternetê kontrol bike.", - "no_results": "Encam nade" + "no_results": "Encam tune" } }, "register": { @@ -247,8 +247,8 @@ "placeholder": "e-name" }, "password": { - "placeholder": "şîfre", - "hint": "Şîfreya we herî kêm heşt tîpan hewce dike" + "placeholder": "pêborîn", + "hint": "Pêborîna te herî kêm divê ji 8 tîpan pêk bê" }, "invite": { "registration_user_invite_request": "Tu çima dixwazî beşdar bibî?" @@ -258,7 +258,7 @@ "item": { "username": "Navê bikarhêner", "email": "E-name", - "password": "Şîfre", + "password": "Pêborîn", "agreement": "Lihevhatin", "locale": "Herêm", "reason": "Sedem" @@ -279,7 +279,7 @@ "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)" + "password_too_short": "Pêborîn pir kurt e (divê herî kêm 8 tîp be)" } } }, @@ -372,7 +372,7 @@ "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", + "enable_content_warning": "Hişyariya naverokê çalak bike", "disable_content_warning": "Hişyariya naverokê neçalak bike", "post_visibility_menu": "Menuya Xuyabûna Şandiyê" }, @@ -387,12 +387,12 @@ }, "profile": { "dashboard": { - "posts": "şandîyan", + "posts": "şandî", "following": "dişopîne", - "followers": "şopîneran" + "followers": "şopîner" }, "fields": { - "add_row": "Rêzê lê zêde bike", + "add_row": "Rêzê tevlî bike", "placeholder": { "label": "Nîşan", "content": "Naverok" From 39bb50f539bc1bfb1cc518aef5301d59901fd13c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 8 Nov 2021 12:38:11 +0100 Subject: [PATCH 66/87] New translations app.json (Kurmanji (Kurdish)) --- .../StringsConvertor/input/kmr_TR/app.json | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index c3666dc60..108cf234c 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -399,7 +399,7 @@ } }, "segmented_control": { - "posts": "Şandîyan", + "posts": "Şandî", "replies": "Bersivan", "media": "Medya" }, @@ -423,11 +423,11 @@ "search": { "title": "Bigere", "search_bar": { - "placeholder": "Li etîketan û bikarhêneran bigerin", - "cancel": "Betal kirin" + "placeholder": "Li hashtag û bikarhêneran bigere", + "cancel": "Dev jê berde" }, "recommend": { - "button_text": "Hemûyé bibîne", + "button_text": "Hemûyan bibîne", "hash_tag": { "title": "Trend li ser Mastodon", "description": "Etîketên ku pir balê dikişînin", @@ -435,7 +435,7 @@ }, "accounts": { "title": "Hesabên ku hûn dikarin hez bikin", - "description": "Dibe ku tu bixwazî van hesaban bişopînî", + "description": "Dibe ku tu bixwazî van ajimêran bişopînî", "follow": "Bişopîne" } }, @@ -443,28 +443,28 @@ "segment": { "all": "Hemû", "people": "Mirov", - "hashtags": "Etîketan", - "posts": "Şandîyan" + "hashtags": "Hashtag", + "posts": "Şandî" }, "empty_state": { "no_results": "Encam tune" }, "recent_search": "Lêgerînên dawî", - "clear": "Paqij bike" + "clear": "Pak bike" } }, "favorite": { - "title": "Bijareyên te" + "title": "Bijarteyên te" }, "notification": { "title": { "Everything": "Her tişt", - "Mentions": "Behs" + "Mentions": "Qalkirin" }, "user_followed_you": "%s te şopand", - "user_favorited your post": "%s posta we bijarte", + "user_favorited your post": "%s şandiya te hez kir", "user_reblogged_your_post": "%s posta we ji nû ve tomar kir", - "user_mentioned_you": "%s behsa te kir", + "user_mentioned_you": "%s qale te kir", "user_requested_to_follow_you": "%s daxwaza şopandina te kir", "user_your_poll_has_ended": "%s Anketa te qediya", "keyobard": { From 8d9c8371617a891b04b10816f060d24ef8ffb8ec Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 8 Nov 2021 12:38:14 +0100 Subject: [PATCH 67/87] New translations Intents.strings (Kurmanji (Kurdish)) --- .../Intents/input/kmr_TR/Intents.strings | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Localization/StringsConvertor/Intents/input/kmr_TR/Intents.strings b/Localization/StringsConvertor/Intents/input/kmr_TR/Intents.strings index 3e1c69fc3..13a86e0c0 100644 --- a/Localization/StringsConvertor/Intents/input/kmr_TR/Intents.strings +++ b/Localization/StringsConvertor/Intents/input/kmr_TR/Intents.strings @@ -24,15 +24,15 @@ "Zo4jgJ" = "Xuyaniya şandiyê"; -"apSxMG-dYQ5NN" = "Vebijarkên ${count} hene ku li gorî 'Giştî' ne."; +"apSxMG-dYQ5NN" = "Vebijarkên ${count} hene ku li gorî 'Gelemperî' ne."; -"apSxMG-ehFLjY" = "Vebijarkên ${count} hene ku li gorî 'Tenê Şopandin' hene."; +"apSxMG-ehFLjY" = "Vebijarkên ${count} hene ku li gorî 'Tenê Şopaneran' hene."; -"ayoYEb-dYQ5NN" = "${content}, Giştî"; +"ayoYEb-dYQ5NN" = "${content}, Gelemperî"; "ayoYEb-ehFLjY" = "${content}, Tenê şopînêr"; -"dUyuGg" = "Li ser Mastodon bişînin"; +"dUyuGg" = "Di Mastodon de biweşîne"; "dYQ5NN" = "Gelemperî"; @@ -42,10 +42,10 @@ "k7dbKQ" = "Şandî bi serkeftî hate şandin."; -"oGiqmY-dYQ5NN" = "Tenê ji bo pejirandinê, we 'Giştî' dixwest?"; +"oGiqmY-dYQ5NN" = "Tenê ji bo pejirandinê, te 'Gelemperî' dixwest?"; -"oGiqmY-ehFLjY" = "Tenê ji bo piştrastkirinê, we 'Tenê Şopdarên' dixwest?"; +"oGiqmY-ehFLjY" = "Tenê ji bo pejirandinê, te 'Tenê Şopîner' dixwest?"; "rM6dvp" = "Girêdan"; -"ryJLwG" = "Bi serkeftî hat şandin. "; +"ryJLwG" = "Şandî bi serkeftî hate şandin. "; From 287a6dc6150d53d767ac6e515618b9cf49738626 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 8 Nov 2021 14:09:54 +0100 Subject: [PATCH 68/87] New translations app.json (Kurmanji (Kurdish)) --- .../StringsConvertor/input/kmr_TR/app.json | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index 108cf234c..c360eb430 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -226,7 +226,7 @@ }, "empty_state": { "finding_servers": "Peydakirina rajekarên berdest...", - "bad_network": "Di dema barkirina daneyan da tiştek xelet derket. Girêdana xwe ya înternetê kontrol bike.", + "bad_network": "Di dema barkirina daneyan da çewtî derket. Girêdana xwe ya înternetê kontrol bike.", "no_results": "Encam tune" } }, @@ -259,38 +259,38 @@ "username": "Navê bikarhêner", "email": "E-name", "password": "Pêborîn", - "agreement": "Lihevhatin", - "locale": "Herêm", + "agreement": "Peyman", + "locale": "Zimanê navrûyê", "reason": "Sedem" }, "reason": { - "blocked": "%s peydekerê e-nameya bêdestûr dihewîne", - "unreachable": "%s xuya nake", + "blocked": "%s peydekerê e-peyamê yê qedexekirî dihewîne", + "unreachable": "%s xuya ye ku tune ye", "taken": "%s jixwe tê bikaranîn", - "reserved": "%s peyveke mifteya veqetandî ye", - "accepted": "%s divê were qebûlkirin", + "reserved": "%s peyveke parastî ye", + "accepted": "%s divê were pejirandin", "blank": "%s pêwist e", "invalid": "%s ne derbasdar e", - "too_long": "%s gelekî dirêj e", + "too_long": "%s pir dirêj e", "too_short": "%s pir kurt e", - "inclusion": "%s nirxeke ku tê destekirin nîn e" + "inclusion": "%s ne nirxek piştgirî ye" }, "special": { - "username_invalid": "Navê bikarhêner divê tenê tîpên alfanumerîk û binxet hebe", + "username_invalid": "Navê bikarhêner divê tenê ji tîpên alfajimarî û binxêz pêk be", "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", + "email_invalid": "Ev navnîşaneke e-nameyê ne derbasdar e", "password_too_short": "Pêborîn pir kurt e (divê herî kêm 8 tîp be)" } } }, "server_rules": { - "title": "Hin qaîdeyên bingehîn.", + "title": "Hinek rêzikê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ê", + "prompt": "Bi domandinê, tu ji bo %s di bin mercên bikaranînê û polîtîkaya nepenîtiyê dipejirînî.", + "terms_of_service": "mercên bikaranînê", + "privacy_policy": "polîtikaya nihêniyê", "button": { - "confirm": "Ez tev dibim" + "confirm": "Ez dipejirînim" } }, "confirm_email": { @@ -374,15 +374,15 @@ "custom_emoji_picker": "Hilbijêrê emojî yên kesanekirî", "enable_content_warning": "Hişyariya naverokê çalak bike", "disable_content_warning": "Hişyariya naverokê neçalak bike", - "post_visibility_menu": "Menuya Xuyabûna Şandiyê" + "post_visibility_menu": "Kulîna 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" + "discard_post": "Şandî paşguh bike", + "publish_post": "Şandiyê biweşîne", + "toggle_poll": "Rapirsiyê biguherîne", + "toggle_content_warning": "Hişyariya naverokê biguherîne", + "append_attachment_entry": "Pêvek tevlî bike - %s", + "select_visibility_entry": "Xuyabûnê hilbijêre - %s" } }, "profile": { @@ -400,17 +400,17 @@ }, "segmented_control": { "posts": "Şandî", - "replies": "Bersivan", + "replies": "Bersiv", "media": "Medya" }, "relationship_action_alert": { "confirm_unmute_user": { - "title": "Hesabê ji bê deng rake", - "message": "Ji bo vekirina bê dengkirinê bipejirin %s" + "title": "Ajimêrê bêdeng neke", + "message": "Ji bo vekirina bêdengkirinê bipejirîne %s" }, "confirm_unblock_usre": { - "title": "Hesabê ji bloke rake", - "message": "Ji bo rakirina blokê bipejirin %s" + "title": "Astengiyê li ser ajimêr rake", + "message": "Ji bo rakirina astengkirinê bipejirîne %s" } } }, @@ -429,12 +429,12 @@ "recommend": { "button_text": "Hemûyan bibîne", "hash_tag": { - "title": "Trend li ser Mastodon", - "description": "Etîketên ku pir balê dikişînin", + "title": "Rojev li ser Mastodon", + "description": "Hashtag ên ku pir balê dikişînin", "people_talking": "%s kes diaxivin" }, "accounts": { - "title": "Hesabên ku hûn dikarin hez bikin", + "title": "Ajimêrên ku belkî tu jê hez bikî", "description": "Dibe ku tu bixwazî van ajimêran bişopînî", "follow": "Bişopîne" } @@ -465,11 +465,11 @@ "user_favorited your post": "%s şandiya te hez kir", "user_reblogged_your_post": "%s posta we ji nû ve tomar kir", "user_mentioned_you": "%s qale te kir", - "user_requested_to_follow_you": "%s daxwaza şopandina te kir", - "user_your_poll_has_ended": "%s Anketa te qediya", + "user_requested_to_follow_you": "%s dixwazê te bişopîne", + "user_your_poll_has_ended": "Rapirsîya te qediya", "keyobard": { "show_everything": "Her tiştî nîşan bide", - "show_mentions": "Behskirîya nîşan bike" + "show_mentions": "Qalkirinan nîşan bike" } }, "thread": { @@ -488,8 +488,8 @@ "notifications": { "title": "Agahdarî", "favorites": "Şandiyên min hez kir", - "follows": "Min şopand", - "boosts": "Şandiya min ji nû ve binivîsine", + "follows": "Min dişopîne", + "boosts": "Şandiya min ji nû ve nivîsand", "mentions": "Qale min kir", "trigger": { "anyone": "her kes", From 832b146c826e987c9094555f183ef25ee6082575 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 10 Nov 2021 17:55:12 +0800 Subject: [PATCH 69/87] feat: update list fetch trigger logic for UserTimeline scene --- Mastodon.xcodeproj/project.pbxproj | 4 ++ .../xcschemes/xcschememanagement.plist | 8 +-- .../Timeline/UserTimelineViewController.swift | 34 ++++++---- .../Timeline/UserTimelineViewModel.swift | 1 + .../ViewModel/ListBatchFetchViewModel.swift | 68 +++++++++++++++++++ 5 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 Mastodon/Scene/Share/ViewModel/ListBatchFetchViewModel.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index bad59c2b5..d7bab5217 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -377,6 +377,7 @@ DB71FD5225F8CCAA00512AE1 /* APIService+Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB71FD5125F8CCAA00512AE1 /* APIService+Status.swift */; }; DB72601C25E36A2100235243 /* MastodonServerRulesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB72601B25E36A2100235243 /* MastodonServerRulesViewController.swift */; }; DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */; }; + DB7274F4273BB9B200577D95 /* ListBatchFetchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7274F3273BB9B200577D95 /* ListBatchFetchViewModel.swift */; }; DB73B490261F030A002E9E9F /* SafariActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB73B48F261F030A002E9E9F /* SafariActivity.swift */; }; DB73BF3B2711885500781945 /* UserDefaults+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB73BF3A2711885500781945 /* UserDefaults+Notification.swift */; }; DB73BF4127118B6D00781945 /* Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB73BF4027118B6D00781945 /* Instance.swift */; }; @@ -1195,6 +1196,7 @@ DB71FD5125F8CCAA00512AE1 /* APIService+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Status.swift"; sourceTree = ""; }; DB72601B25E36A2100235243 /* MastodonServerRulesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonServerRulesViewController.swift; sourceTree = ""; }; DB72602625E36A6F00235243 /* MastodonServerRulesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonServerRulesViewModel.swift; sourceTree = ""; }; + DB7274F3273BB9B200577D95 /* ListBatchFetchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListBatchFetchViewModel.swift; sourceTree = ""; }; DB73B48F261F030A002E9E9F /* SafariActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariActivity.swift; sourceTree = ""; }; DB73BF3A2711885500781945 /* UserDefaults+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Notification.swift"; sourceTree = ""; }; DB73BF4027118B6D00781945 /* Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instance.swift; sourceTree = ""; }; @@ -2972,6 +2974,7 @@ DB9D6C2225E502C60051B173 /* MosaicImageViewModel.swift */, 2DA6055025F74407006356F9 /* AudioContainerViewModel.swift */, 5DF1054625F8870E00D6C0D4 /* VideoPlayerViewModel.swift */, + DB7274F3273BB9B200577D95 /* ListBatchFetchViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -4233,6 +4236,7 @@ 2D24E11D2626D8B100A59D4F /* NotificationStatusTableViewCell.swift in Sources */, DB6C8C0F25F0A6AE00AAA452 /* Mastodon+Entity+Error.swift in Sources */, DB1E346825F518E20079D7DF /* CategoryPickerSection.swift in Sources */, + DB7274F4273BB9B200577D95 /* ListBatchFetchViewModel.swift in Sources */, 2D61254D262547C200299647 /* APIService+Notification.swift in Sources */, DB040ED126538E3D00BEE9D8 /* Trie.swift in Sources */, DB73BF4B27140C0800781945 /* UITableViewDiffableDataSource.swift in Sources */, diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 7aa368605..921a52196 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 42 + 36 CoreDataStack.xcscheme_^#shared#^_ orderHint - 43 + 38 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 45 + 39 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 44 + 37 SuppressBuildableAutocreation diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift index 42e9376cf..4bee3b8af 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift @@ -72,6 +72,16 @@ extension UserTimelineViewController { statusTableViewCellDelegate: self ) + // setup batch fetch + viewModel.listBatchFetchViewModel.setup(scrollView: tableView) + viewModel.listBatchFetchViewModel.shouldFetch + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + guard let self = self else { return } + self.viewModel.stateMachine.enter(UserTimelineViewModel.State.Loading.self) + } + .store(in: &disposeBag) + // trigger user timeline loading Publishers.CombineLatest( viewModel.domain.removeDuplicates().eraseToAnyPublisher(), @@ -104,11 +114,11 @@ extension UserTimelineViewController { extension UserTimelineViewController: StatusTableViewControllerAspect { } // MARK: - UIScrollViewDelegate -extension UserTimelineViewController { - func scrollViewDidScroll(_ scrollView: UIScrollView) { - aspectScrollViewDidScroll(scrollView) - } -} +//extension UserTimelineViewController { +// func scrollViewDidScroll(_ scrollView: UIScrollView) { +// aspectScrollViewDidScroll(scrollView) +// } +//} // MARK: - TableViewCellHeightCacheableContainer extension UserTimelineViewController: TableViewCellHeightCacheableContainer { @@ -186,13 +196,13 @@ extension UserTimelineViewController: ScrollViewContainer { } // MARK: - LoadMoreConfigurableTableViewContainer -extension UserTimelineViewController: LoadMoreConfigurableTableViewContainer { - typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell - typealias LoadingState = UserTimelineViewModel.State.Loading - - var loadMoreConfigurableTableView: UITableView { return tableView } - var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.stateMachine } -} +//extension UserTimelineViewController: LoadMoreConfigurableTableViewContainer { +// typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell +// typealias LoadingState = UserTimelineViewModel.State.Loading +// +// var loadMoreConfigurableTableView: UITable``````View { return tableView } +// var loadMoreConfigurableStateMachine: GKStateMachine { return viewModel.stateMachine } +//} extension UserTimelineViewController { override var keyCommands: [UIKeyCommand]? { diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift index 42edafb0f..5bf520d6d 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel.swift @@ -23,6 +23,7 @@ final class UserTimelineViewModel { let userID: CurrentValueSubject let queryFilter: CurrentValueSubject let statusFetchedResultsController: StatusFetchedResultsController + let listBatchFetchViewModel = ListBatchFetchViewModel() var cellFrameCache = NSCache() let isBlocking = CurrentValueSubject(false) diff --git a/Mastodon/Scene/Share/ViewModel/ListBatchFetchViewModel.swift b/Mastodon/Scene/Share/ViewModel/ListBatchFetchViewModel.swift new file mode 100644 index 000000000..78eaf6ae3 --- /dev/null +++ b/Mastodon/Scene/Share/ViewModel/ListBatchFetchViewModel.swift @@ -0,0 +1,68 @@ +// +// ListBatchFetchViewModel.swift +// Mastodon +// +// Created by Cirno MainasuK on 2021-11-10. +// + +import UIKit +import Combine + +// ref: Texture.ASBatchFetchingDelegate +final class ListBatchFetchViewModel { + + var disposeBag = Set() + + // timer running on `common` mode + let timerPublisher = Timer.publish(every: 1.0, on: .main, in: .common) + .autoconnect() + .share() + .eraseToAnyPublisher() + + // input + private(set) weak var scrollView: UIScrollView? + let hasMore = CurrentValueSubject(true) + + // output + let shouldFetch = PassthroughSubject() + + init() { + Publishers.CombineLatest( + hasMore, + timerPublisher + ) + .sink { [weak self] hasMore, _ in + guard let self = self else { return } + guard hasMore else { return } + guard let scrollView = self.scrollView else { return } + + // skip trigger if user interacting + if scrollView.isDragging || scrollView.isTracking { return } + + // send fetch request + if scrollView.contentSize.height < scrollView.frame.height { + self.shouldFetch.send() + } else { + let frame = scrollView.frame + let contentOffset = scrollView.contentOffset + let contentSize = scrollView.contentSize + + let visibleBottomY = contentOffset.y + frame.height + let offset = 2 * frame.height + let fetchThrottleOffsetY = contentSize.height - offset + + if visibleBottomY > fetchThrottleOffsetY { + self.shouldFetch.send() + } + } + } + .store(in: &disposeBag) + } + +} + +extension ListBatchFetchViewModel { + func setup(scrollView: UIScrollView) { + self.scrollView = scrollView + } +} From b609e010aeb394927cff1ef7d5c9e72b5b57be3c Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 10 Nov 2021 17:55:37 +0800 Subject: [PATCH 70/87] fix: split view column separator line color not set to theme style issue --- Mastodon/Scene/Root/RootSplitViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index 505e9089d..e9d7549bd 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -142,7 +142,7 @@ extension RootSplitViewController { private func setupBackground(theme: Theme) { // this set column separator line color - view.backgroundColor = .opaqueSeparator + view.backgroundColor = theme.separator } } From 9d1c1322d9b5c9009d88d6e277535bd85503a488 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 10 Nov 2021 17:56:16 +0800 Subject: [PATCH 71/87] chore: update version to 1.2.0 (86) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon.xcodeproj/project.pbxproj | 64 +++++++++---------- .../xcschemes/xcschememanagement.plist | 8 +-- Mastodon/Info.plist | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 11 files changed, 45 insertions(+), 45 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 5e09203d5..8dc24c39e 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index 5e09203d5..8dc24c39e 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index 5e09203d5..8dc24c39e 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index d7bab5217..55fc0af75 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4919,7 +4919,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4948,7 +4948,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5056,11 +5056,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5087,11 +5087,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5116,11 +5116,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5146,11 +5146,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5213,7 +5213,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5238,7 +5238,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5263,7 +5263,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5288,7 +5288,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5313,7 +5313,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5338,7 +5338,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5363,7 +5363,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5388,7 +5388,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5479,7 +5479,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5546,11 +5546,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5595,7 +5595,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5620,11 +5620,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5716,7 +5716,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5783,11 +5783,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5832,7 +5832,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5857,11 +5857,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 85; + DYLIB_CURRENT_VERSION = 86; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5887,7 +5887,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5911,7 +5911,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 85; + CURRENT_PROJECT_VERSION = 86; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 921a52196..2b0badaea 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 36 + 43 CoreDataStack.xcscheme_^#shared#^_ orderHint - 38 + 44 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 39 + 42 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 37 + 45 SuppressBuildableAutocreation diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index d788a77cb..98e4a1eb0 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 85 + 86 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index ac52ba389..57166c457 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 5e09203d5..8dc24c39e 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 5e09203d5..8dc24c39e 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index ae1666ce1..803a158bb 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 1b8fa72ce..7ffaa7806 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 85 + 86 NSExtension NSExtensionAttributes From 06ea9a22b918bf0dcfe05364ac2a92d39deeb455 Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 10 Nov 2021 17:58:37 +0800 Subject: [PATCH 72/87] chore: update i18n resources --- .../es-419.lproj/Localizable.strings | 6 +- .../Resources/ku-TR.lproj/Localizable.strings | 194 +++++++++--------- .../Scene/Root/Sidebar/SidebarViewModel.swift | 4 +- MastodonIntent/ku-TR.lproj/Intents.strings | 14 +- 4 files changed, 109 insertions(+), 109 deletions(-) diff --git a/Mastodon/Resources/es-419.lproj/Localizable.strings b/Mastodon/Resources/es-419.lproj/Localizable.strings index 3ffd12049..cf97fe803 100644 --- a/Mastodon/Resources/es-419.lproj/Localizable.strings +++ b/Mastodon/Resources/es-419.lproj/Localizable.strings @@ -28,7 +28,7 @@ Por favor, revisá tu conexión a Internet."; "Common.Controls.Actions.Back" = "Volver"; "Common.Controls.Actions.BlockDomain" = "Bloquear a %@"; "Common.Controls.Actions.Cancel" = "Cancelar"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "Redactar"; "Common.Controls.Actions.Confirm" = "Confirmar"; "Common.Controls.Actions.Continue" = "Continuar"; "Common.Controls.Actions.CopyPhoto" = "Copiar foto"; @@ -191,8 +191,8 @@ y no se puede subir a Mastodon."; pulsá en el enlace para confirmar tu cuenta."; "Scene.ConfirmEmail.Title" = "Una última cosa."; "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.Follower.Footer" = "No se muestran los seguidores de otros servidores."; +"Scene.Following.Footer" = "No se muestran las cuentas de otros servidores que seguís."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevos mensajes"; "Scene.HomeTimeline.NavigationBarState.Offline" = "Desconectado"; "Scene.HomeTimeline.NavigationBarState.Published" = "¡Enviado!"; diff --git a/Mastodon/Resources/ku-TR.lproj/Localizable.strings b/Mastodon/Resources/ku-TR.lproj/Localizable.strings index 7f84febe0..d0d0f294e 100644 --- a/Mastodon/Resources/ku-TR.lproj/Localizable.strings +++ b/Mastodon/Resources/ku-TR.lproj/Localizable.strings @@ -1,21 +1,21 @@ "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.CleanCache.Message" = "Pêşbîra %@ biserketî hate pakkirin."; +"Common.Alerts.CleanCache.Title" = "Pêşbîrê pak 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.DiscardPostContent.Message" = "Bipejrîne ku naveroka şandiyê ya hatiye nivîsandin paşguh bikî."; +"Common.Alerts.DiscardPostContent.Title" = "Reşnivîsê paşguh bike"; "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.EditProfileFailure.Title" = "Di serrastkirina profîlê çewtî"; "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.Message" = "Ji kerema xwe mafê bide gihîştina wênegehê çalak bike da ku wêne werin tomarkirin."; "Common.Alerts.SavePhotoFailure.Title" = "Tomarkirina wêneyê têkçû"; "Common.Alerts.ServerError.Title" = "Çewtiya rajekar"; "Common.Alerts.SignOut.Confirm" = "Derkeve"; @@ -31,13 +31,13 @@ Jkx girêdana înternetê xwe kontrol bike."; "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.CopyPhoto" = "Wêneyê jê bigire"; "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.FindPeople" = "Mirovan bo şopandinê bibîne"; +"Common.Controls.Actions.ManuallySearch" = "Ji devlê bi destan lêgerînê bike"; "Common.Controls.Actions.Next" = "Pêş"; "Common.Controls.Actions.Ok" = "BAŞ E"; "Common.Controls.Actions.Open" = "Veke"; @@ -48,7 +48,7 @@ Jkx girêdana înternetê xwe kontrol bike."; "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.SavePhoto" = "Wêneyê tomar bike"; "Common.Controls.Actions.SeeMore" = "Bêtir bibîne"; "Common.Controls.Actions.Settings" = "Sazkarî"; "Common.Controls.Actions.Share" = "Parve bike"; @@ -71,7 +71,7 @@ Jkx girêdana înternetê xwe kontrol 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.Request" = "Daxwaz bike"; "Common.Controls.Friendship.Unblock" = "Astengiyê rake"; "Common.Controls.Friendship.UnblockUser" = "%@ asteng neke"; "Common.Controls.Friendship.Unmute" = "Bêdeng neke"; @@ -80,58 +80,58 @@ Jkx girêdana înternetê xwe kontrol bike."; "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.SegmentedControl.NextSection" = "Beşa pêş"; +"Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "Beşa paş"; "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.PreviewImage" = "Pêşdîtina wêneyê"; "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.ToggleContentWarning" = "Hişyariya naverokê biguherîne"; +"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Li ser şandiyê bijarte biguherîne"; "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.Favorite" = "Bijarte"; +"Common.Controls.Status.Actions.Menu" = "Kulîn"; +"Common.Controls.Status.Actions.Reblog" = "Ji nû ve nivîsandin"; "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.Actions.Unfavorite" = "Nebijarte"; +"Common.Controls.Status.Actions.Unreblog" = "Ji nû ve nivîsandinê vegere"; "Common.Controls.Status.ContentWarning" = "Hişyariya naverokê"; -"Common.Controls.Status.MediaContentWarning" = "Ji bo aşkerakirinê derekî bitikîne"; +"Common.Controls.Status.MediaContentWarning" = "Ji bo eşkerekirinê li derekî bitikîne"; "Common.Controls.Status.Poll.Closed" = "Girtî"; -"Common.Controls.Status.Poll.Vote" = "Deng"; +"Common.Controls.Status.Poll.Vote" = "Deng bide"; "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.Emoji" = "Emojî"; +"Common.Controls.Status.Tag.Hashtag" = "Hashtag"; "Common.Controls.Status.Tag.Link" = "Girêdan"; -"Common.Controls.Status.Tag.Mention" = "Behs"; +"Common.Controls.Status.Tag.Mention" = "Qalkirin"; "Common.Controls.Status.Tag.Url" = "URL"; -"Common.Controls.Status.UserReblogged" = "%@ ji nû ve hat blogkirin"; +"Common.Controls.Status.UserReblogged" = "%@ ji nû ve hate nivîsandin"; "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î. +"Common.Controls.Timeline.Header.BlockedWarning" = "Tu nikarî profîla vî/ê bikarhênerî bibînî +heya ku ew astengiyê li ser te rakin."; +"Common.Controls.Timeline.Header.BlockingWarning" = "Tu nikarî profîla vî/ê bikarhênerî bibînî +Heya ku tu astengiyê li ser wî/ê ranekî. 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.NoStatusFound" = "Tu şandî nehate dîtin"; +"Common.Controls.Timeline.Header.SuspendedWarning" = "Ev bikarhêner hatiye rawestandin."; "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î. +Heya ku tu astengiyê li ser wî/ê ranekî. 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.Header.UserSuspendedWarning" = "Ajimêra %@ hatiye rawestandin."; +"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Şandiyên wendayî bar bike"; +"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Şandiyên wendayî tên barkirin..."; "Common.Controls.Timeline.Loader.ShowMoreReplies" = "Bêtir bersivan nîşan bide"; "Common.Controls.Timeline.Timestamp.Now" = "Niha"; "Scene.AccountList.AddAccount" = "Ajimêr tevlî bike"; @@ -141,8 +141,8 @@ Profîla te ji wan ra wiha xuya dike."; "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.EnableContentWarning" = "Hişyariya naverokê çalak bike"; +"Scene.Compose.Accessibility.PostVisibilityMenu" = "Kulîna xuyabûna şandiyê"; "Scene.Compose.Accessibility.RemovePoll" = "Rapirsî rake"; "Scene.Compose.Attachment.AttachmentBroken" = "Ev %@ naxebite û nayê barkirin li ser Mastodon."; @@ -154,12 +154,12 @@ Profîla te ji wan ra wiha xuya dike."; "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.Keyboard.AppendAttachmentEntry" = "Pêvek tevlî bike - %@"; +"Scene.Compose.Keyboard.DiscardPost" = "Şandî paşguh bike"; +"Scene.Compose.Keyboard.PublishPost" = "Şandiyê biweşîne"; +"Scene.Compose.Keyboard.SelectVisibilityEntry" = "Xuyabûnê hilbijêre - %@"; +"Scene.Compose.Keyboard.ToggleContentWarning" = "Hişyariya naverokê biguherîne"; +"Scene.Compose.Keyboard.TogglePoll" = "Rapirsiyê biguherîne"; "Scene.Compose.MediaSelection.Browse" = "Bigere"; "Scene.Compose.MediaSelection.Camera" = "Wêne bikişîne"; "Scene.Compose.MediaSelection.PhotoLibrary" = "Wênegeh"; @@ -190,7 +190,7 @@ Profîla te ji wan ra wiha xuya dike."; "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.Favorite.Title" = "Bijarteyê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"; @@ -199,57 +199,57 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "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.Keyobard.ShowMentions" = "Qalkirinan 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.Title.Mentions" = "Qalkirin"; +"Scene.Notification.UserFavorited Your Post" = "%@ şandiya te hez kir"; "Scene.Notification.UserFollowedYou" = "%@ te şopand"; -"Scene.Notification.UserMentionedYou" = "%@ behsa te kir"; +"Scene.Notification.UserMentionedYou" = "%@ qale 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.Notification.UserRequestedToFollowYou" = "%@ dixwazê te bişopîne"; +"Scene.Notification.UserYourPollHasEnded" = "Rapirsîya 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.Followers" = "şopîner"; "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.Dashboard.Posts" = "şandî"; +"Scene.Profile.Fields.AddRow" = "Rêzê tevlî 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.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Ji bo rakirina astengkirinê bipejirîne %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Astengiyê li ser ajimêr rake"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Ji bo vekirina bêdengkirinê bipejirîne %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Ajimêrê bêdeng neke"; "Scene.Profile.SegmentedControl.Media" = "Medya"; -"Scene.Profile.SegmentedControl.Posts" = "Şandîyan"; -"Scene.Profile.SegmentedControl.Replies" = "Bersivan"; -"Scene.Register.Error.Item.Agreement" = "Lihevhatin"; +"Scene.Profile.SegmentedControl.Posts" = "Şandî"; +"Scene.Profile.SegmentedControl.Replies" = "Bersiv"; +"Scene.Register.Error.Item.Agreement" = "Peyman"; "Scene.Register.Error.Item.Email" = "E-name"; -"Scene.Register.Error.Item.Locale" = "Herêm"; -"Scene.Register.Error.Item.Password" = "Şîfre"; +"Scene.Register.Error.Item.Locale" = "Zimanê navrûyê"; +"Scene.Register.Error.Item.Password" = "Pêborîn"; "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.Accepted" = "%@ divê were pejirandin"; "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.Blocked" = "%@ peydekerê e-peyamê yê qedexekirî dihewîne"; +"Scene.Register.Error.Reason.Inclusion" = "%@ ne nirxek piştgirî ye"; "Scene.Register.Error.Reason.Invalid" = "%@ ne derbasdar e"; -"Scene.Register.Error.Reason.Reserved" = "%@ peyveke mifteya veqetandî ye"; +"Scene.Register.Error.Reason.Reserved" = "%@ peyveke parastî ye"; "Scene.Register.Error.Reason.Taken" = "%@ jixwe tê bikaranîn"; -"Scene.Register.Error.Reason.TooLong" = "%@ gelekî dirêj e"; +"Scene.Register.Error.Reason.TooLong" = "%@ pir 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.Reason.Unreachable" = "%@ xuya ye ku tune ye"; +"Scene.Register.Error.Special.EmailInvalid" = "Ev navnîşaneke e-nameyê ne derbasdar e"; +"Scene.Register.Error.Special.PasswordTooShort" = "Pêborîn pir kurt e (divê herî kêm 8 tîp be)"; +"Scene.Register.Error.Special.UsernameInvalid" = "Navê bikarhêner divê tenê ji tîpên alfajimarî û binxêz pêk be"; "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.Password.Hint" = "Pêborîna te herî kêm divê ji 8 tîpan pêk bê"; +"Scene.Register.Input.Password.Placeholder" = "pêborîn"; "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."; @@ -261,22 +261,22 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "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.Description" = "Dibe ku tu bixwazî van ajimêran 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.Accounts.Title" = "Ajimêrên ku belkî tu jê hez bikî"; +"Scene.Search.Recommend.ButtonText" = "Hemûyan bibîne"; +"Scene.Search.Recommend.HashTag.Description" = "Hashtag ê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.Recommend.HashTag.Title" = "Rojev li ser Mastodon"; +"Scene.Search.SearchBar.Cancel" = "Dev jê berde"; +"Scene.Search.SearchBar.Placeholder" = "Li hashtag û bikarhêneran bigere"; +"Scene.Search.Searching.Clear" = "Pak 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.Hashtags" = "Hashtag"; "Scene.Search.Searching.Segment.People" = "Mirov"; -"Scene.Search.Searching.Segment.Posts" = "Şandîyan"; +"Scene.Search.Searching.Segment.Posts" = "Şandî"; "Scene.Search.Title" = "Bigere"; "Scene.ServerPicker.Button.Category.Academia" = "akademî"; "Scene.ServerPicker.Button.Category.Activism" = "çalakî"; @@ -294,21 +294,21 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "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.EmptyState.BadNetwork" = "Di dema barkirina daneyan da çewtî derket. Girêdana xwe ya înternetê kontrol bike."; +"Scene.ServerPicker.EmptyState.FindingServers" = "Peydakirina rajekarên berdest..."; +"Scene.ServerPicker.EmptyState.NoResults" = "Encam tune"; +"Scene.ServerPicker.Input.Placeholder" = "Rajekarekî bibîne an jî beşdarî ya xwe bibe..."; +"Scene.ServerPicker.Label.Category" = "BEŞ"; "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.Button.Confirm" = "Ez dipejirînim"; +"Scene.ServerRules.PrivacyPolicy" = "polîtikaya nihêniyê"; +"Scene.ServerRules.Prompt" = "Bi domandinê, tu ji bo %@ di bin mercên bikaranînê û polîtîkaya nepenîtiyê dipejirînî."; "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.ServerRules.TermsOfService" = "mercên bikaranînê"; +"Scene.ServerRules.Title" = "Hinek rêzikê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"; @@ -319,9 +319,9 @@ Her kîjan rajekar be."; "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.Boosts" = "Şandiya min ji nû ve nivîsand"; "Scene.Settings.Section.Notifications.Favorites" = "Şandiyên min hez kir"; -"Scene.Settings.Section.Notifications.Follows" = "Min şopand"; +"Scene.Settings.Section.Notifications.Follows" = "Min dişopîne"; "Scene.Settings.Section.Notifications.Mentions" = "Qale min kir"; "Scene.Settings.Section.Notifications.Title" = "Agahdarî"; "Scene.Settings.Section.Notifications.Trigger.Anyone" = "her kes"; diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift index 5ababf161..baa468d2a 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift @@ -145,7 +145,7 @@ extension SidebarViewModel { return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item) case .compose: let item = SidebarListContentView.Item( - title: "Compose", // TODO: update i18n + title: L10n.Common.Controls.Actions.compose image: UIImage(systemName: "square.and.pencil")!, imageURL: nil ) @@ -190,7 +190,7 @@ extension SidebarViewModel { } let item = SidebarListContentView.Item( - title: "Compose", // FIXME: + title: L10n.Common.Controls.Actions.compose, image: UIImage(systemName: "square.and.pencil")!, imageURL: nil ) diff --git a/MastodonIntent/ku-TR.lproj/Intents.strings b/MastodonIntent/ku-TR.lproj/Intents.strings index 3e1c69fc3..13a86e0c0 100644 --- a/MastodonIntent/ku-TR.lproj/Intents.strings +++ b/MastodonIntent/ku-TR.lproj/Intents.strings @@ -24,15 +24,15 @@ "Zo4jgJ" = "Xuyaniya şandiyê"; -"apSxMG-dYQ5NN" = "Vebijarkên ${count} hene ku li gorî 'Giştî' ne."; +"apSxMG-dYQ5NN" = "Vebijarkên ${count} hene ku li gorî 'Gelemperî' ne."; -"apSxMG-ehFLjY" = "Vebijarkên ${count} hene ku li gorî 'Tenê Şopandin' hene."; +"apSxMG-ehFLjY" = "Vebijarkên ${count} hene ku li gorî 'Tenê Şopaneran' hene."; -"ayoYEb-dYQ5NN" = "${content}, Giştî"; +"ayoYEb-dYQ5NN" = "${content}, Gelemperî"; "ayoYEb-ehFLjY" = "${content}, Tenê şopînêr"; -"dUyuGg" = "Li ser Mastodon bişînin"; +"dUyuGg" = "Di Mastodon de biweşîne"; "dYQ5NN" = "Gelemperî"; @@ -42,10 +42,10 @@ "k7dbKQ" = "Şandî bi serkeftî hate şandin."; -"oGiqmY-dYQ5NN" = "Tenê ji bo pejirandinê, we 'Giştî' dixwest?"; +"oGiqmY-dYQ5NN" = "Tenê ji bo pejirandinê, te 'Gelemperî' dixwest?"; -"oGiqmY-ehFLjY" = "Tenê ji bo piştrastkirinê, we 'Tenê Şopdarên' dixwest?"; +"oGiqmY-ehFLjY" = "Tenê ji bo pejirandinê, te 'Tenê Şopîner' dixwest?"; "rM6dvp" = "Girêdan"; -"ryJLwG" = "Bi serkeftî hat şandin. "; +"ryJLwG" = "Şandî bi serkeftî hate şandin. "; From 6ac184a42797b84c6de99d284531d9c0b41859fe Mon Sep 17 00:00:00 2001 From: CMK Date: Wed, 10 Nov 2021 18:00:16 +0800 Subject: [PATCH 73/87] chore: update to version 1.2.0 (87) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon.xcodeproj/project.pbxproj | 64 +++++++++---------- .../xcschemes/xcschememanagement.plist | 8 +-- Mastodon/Info.plist | 2 +- .../Scene/Root/Sidebar/SidebarViewModel.swift | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 12 files changed, 46 insertions(+), 46 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 8dc24c39e..9e3842757 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index 8dc24c39e..9e3842757 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index 8dc24c39e..9e3842757 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 55fc0af75..e5118bf8d 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4919,7 +4919,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4948,7 +4948,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5056,11 +5056,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5087,11 +5087,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5116,11 +5116,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5146,11 +5146,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5213,7 +5213,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5238,7 +5238,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5263,7 +5263,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5288,7 +5288,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5313,7 +5313,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5338,7 +5338,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5363,7 +5363,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5388,7 +5388,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5479,7 +5479,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5546,11 +5546,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5595,7 +5595,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5620,11 +5620,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5716,7 +5716,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5783,11 +5783,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5832,7 +5832,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5857,11 +5857,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 86; + DYLIB_CURRENT_VERSION = 87; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5887,7 +5887,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5911,7 +5911,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 86; + CURRENT_PROJECT_VERSION = 87; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index b4fed1ca6..aa6a21a4c 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 51 + 47 CoreDataStack.xcscheme_^#shared#^_ orderHint - 50 + 46 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 53 + 45 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 52 + 48 SuppressBuildableAutocreation diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index 98e4a1eb0..00bab8799 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 86 + 87 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift index baa468d2a..37b46932b 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift @@ -145,7 +145,7 @@ extension SidebarViewModel { return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item) case .compose: let item = SidebarListContentView.Item( - title: L10n.Common.Controls.Actions.compose + title: L10n.Common.Controls.Actions.compose, image: UIImage(systemName: "square.and.pencil")!, imageURL: nil ) diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index 57166c457..986b62577 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 8dc24c39e..9e3842757 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 8dc24c39e..9e3842757 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index 803a158bb..a6cdb01a1 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 7ffaa7806..b5052eb9e 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 86 + 87 NSExtension NSExtensionAttributes From e02decdb5616629bad3361a1ee82ed2884c3b0a0 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 15 Nov 2021 05:20:58 +0100 Subject: [PATCH 74/87] New translations app.json (Arabic) --- .../StringsConvertor/input/ar_SA/app.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Localization/StringsConvertor/input/ar_SA/app.json b/Localization/StringsConvertor/input/ar_SA/app.json index 44aebc154..d37dc8ca6 100644 --- a/Localization/StringsConvertor/input/ar_SA/app.json +++ b/Localization/StringsConvertor/input/ar_SA/app.json @@ -67,7 +67,7 @@ "done": "تمّ", "confirm": "تأكيد", "continue": "واصل", - "compose": "Compose", + "compose": "كِتابة", "cancel": "إلغاء", "discard": "تجاهل", "try_again": "المُحاولة مرة أُخرى", @@ -112,9 +112,9 @@ "open_author_profile": "افتح الملف التعريفي للمؤلف", "open_reblogger_profile": "افتح الملف التعريفي لمشارِك المنشور", "reply_status": "رد على المنشور", - "toggle_reblog": "Toggle Reblog on Post", - "toggle_favorite": "Toggle Favorite on Post", - "toggle_content_warning": "Toggle Content Warning", + "toggle_reblog": "تبديل إعادة تدوين منشور", + "toggle_favorite": "تبديل المفضلة لِمنشور", + "toggle_content_warning": "تبديل تحذير المُحتَوى", "preview_image": "معاينة الصورة" }, "segmented_control": { @@ -128,7 +128,7 @@ "show_post": "اظهر المنشور", "show_user_profile": "اظهر الملف التعريفي للمستخدم", "content_warning": "تحذير عن المحتوى", - "media_content_warning": "Tap anywhere to reveal", + "media_content_warning": "انقر على أي مكان للكشف", "poll": { "vote": "صَوّت", "closed": "انتهى" @@ -180,12 +180,12 @@ }, "header": { "no_status_found": "لا توجد هناك منشورات", - "blocking_warning": "You can’t view this user's profile\nuntil you unblock them.\nYour profile looks like this to them.", + "blocking_warning": "لا يُمكنك الاطلاع على الملف الشخصي لهذا المُستخدِم\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", "user_blocking_warning": "You can’t view %s’s profile\nuntil you unblock them.\nYour profile looks like this to them.", "blocked_warning": "You can’t view this user’s profile\nuntil they unblock you.", "user_blocked_warning": "You can’t view %s’s profile\nuntil they unblock you.", - "suspended_warning": "This user has been suspended.", - "user_suspended_warning": "%s’s account has been suspended." + "suspended_warning": "تمَّ إيقاف هذا المُستخدِم.", + "user_suspended_warning": "لقد أوقِفَ حِساب %s." } } } From 784ae0a747f29e5499c37e6db41020759a23b554 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 15 Nov 2021 06:21:46 +0100 Subject: [PATCH 75/87] New translations app.json (Arabic) --- .../StringsConvertor/input/ar_SA/app.json | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/Localization/StringsConvertor/input/ar_SA/app.json b/Localization/StringsConvertor/input/ar_SA/app.json index d37dc8ca6..3e788d6ce 100644 --- a/Localization/StringsConvertor/input/ar_SA/app.json +++ b/Localization/StringsConvertor/input/ar_SA/app.json @@ -17,14 +17,14 @@ }, "discard_post_content": { "title": "تجاهل المسودة", - "message": "Confirm to discard composed post content." + "message": "أكِّد للتخلص مِن مُحتوى مَنشور مؤلَّف." }, "publish_post_failure": { "title": "أخفقت عملية النشر", - "message": "Failed to publish the post.\nPlease check your internet connection.", + "message": "فَشَلَ نَشر المَنشور.\nيُرجى التحقق من اتصالك بالإنترنت.", "attachments_message": { - "video_attach_with_photo": "Cannot attach a video to a post that already contains images.", - "more_than_one_video": "Cannot attach more than one video." + "video_attach_with_photo": "لا يُمكن إرفاق مقطع مرئي إلى مَنشور يحتوي بالفعل على صُوَر.", + "more_than_one_video": "لا يُمكِنُ إرفاق أكثر مِن مَقطع مرئي واحِد." } }, "edit_profile_failure": { @@ -67,7 +67,7 @@ "done": "تمّ", "confirm": "تأكيد", "continue": "واصل", - "compose": "كِتابة", + "compose": "تأليف", "cancel": "إلغاء", "discard": "تجاهل", "try_again": "المُحاولة مرة أُخرى", @@ -101,7 +101,7 @@ "keyboard": { "common": { "switch_to_tab": "التبديل إلى %s", - "compose_new_post": "إنشاء منشور جديد", + "compose_new_post": "تأليف منشور جديد", "show_favorites": "إظهار المفضلة", "open_settings": "أفتح الإعدادات" }, @@ -192,7 +192,7 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "شبكات التواصل الاجتماعي\nمرة أُخرى بين يديك." }, "server_picker": { "title": "اِختر خادِم،\nأي خادِم.", @@ -226,7 +226,7 @@ }, "empty_state": { "finding_servers": "البحث عن خوادم متوفرة...", - "bad_network": "Something went wrong while loading the data. Check your internet connection.", + "bad_network": "حدث خطأٌ ما أثناء تحميل البيانات. تحقَّق من اتصالك بالإنترنت.", "no_results": "لا توجد نتائج" } }, @@ -264,20 +264,20 @@ "reason": "السبب" }, "reason": { - "blocked": "%s contains a disallowed email provider", - "unreachable": "%s does not seem to exist", - "taken": "%s is already in use", - "reserved": "%s is a reserved keyword", - "accepted": "%s must be accepted", + "blocked": "يحتوي %s على موفِّر خدمة بريد إلكتروني غير مسموح به", + "unreachable": "يبدوا أنَّ %s غير موجود", + "taken": "إنَّ %s مُستخدَمٌ بالفعل", + "reserved": "إنَّ %s عبارة عن كلمة مفتاحيَّة محجوزة", + "accepted": "يجب أن يُقبل %s", "blank": "%s مطلوب", "invalid": "%s غير صالح", "too_long": "%s طويل جداً", "too_short": "%s قصير جدا", - "inclusion": "%s is not a supported value" + "inclusion": "إنَّ %s قيمة غير مدعومة" }, "special": { - "username_invalid": "Username must only contain alphanumeric characters and underscores", - "username_too_long": "Username is too long (can’t be longer than 30 characters)", + "username_invalid": "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط", + "username_too_long": "اسم المستخدم طويل جداً (يجب ألّا يكون أطول من 30 رمز)", "email_invalid": "هذا عنوان بريد إلكتروني غير صالح", "password_too_short": "كلمة المرور قصيرة جداً (يجب أن تكون 8 أحرف على الأقل)" } @@ -302,12 +302,12 @@ }, "dont_receive_email": { "title": "تحقق من بريدك الإلكتروني", - "description": "Check if your email address is correct as well as your junk folder if you haven’t.", + "description": "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك.", "resend_email": "إعادة إرسال البريد الإلكتروني" }, "open_email_app": { "title": "تحقَّق من بريدك الوارِد.", - "description": "We just sent you an email. Check your junk folder if you haven’t.", + "description": "لقد أرسلنا لك بريدًا إلكترونيًا للتو. تحقق من مجلد البريد غير الهام الخاص بك إذا لم تكن قد فعلت ذلك.", "mail": "البريد", "open_email_client": "فتح عميل البريد الإلكتروني" } @@ -323,7 +323,7 @@ }, "suggestion_account": { "title": "ابحث عن أشخاص لمتابعتهم", - "follow_explain": "When you follow someone, you’ll see their posts in your home feed." + "follow_explain": "عِندَ مُتابَعَتِكَ لأحدِهِم، سَوف تَرى مَنشوراته في تغذيَتِكَ الرئيسة." }, "compose": { "title": { @@ -341,9 +341,9 @@ "attachment": { "photo": "صورة", "video": "فيديو", - "attachment_broken": "This %s is broken and can’t be\nuploaded to Mastodon.", - "description_photo": "Describe the photo for the visually-impaired...", - "description_video": "Describe the video for the visually-impaired..." + "attachment_broken": "هذا ال%s مُعطَّل ويتعذَّر رفعه إلى ماستودون.", + "description_photo": "صِف الصورة للمكفوفين...", + "description_video": "صِف المقطع المرئي للمكفوفين..." }, "poll": { "duration_time": "المدة: %s", @@ -356,7 +356,7 @@ "option_number": "الخيار %ld" }, "content_warning": { - "placeholder": "Write an accurate warning here..." + "placeholder": "اكتب تَحذيرًا دَقيقًا هُنا..." }, "visibility": { "public": "للعامة", @@ -365,7 +365,7 @@ "direct": "ففط للأشخاص المشار إليهم" }, "auto_complete": { - "space_to_add": "Space to add" + "space_to_add": "انقر مساحة لإضافتِها" }, "accessibility": { "append_attachment": "إضافة مُرفَق", @@ -374,7 +374,7 @@ "custom_emoji_picker": "منتقي مخصص للإيموجي", "enable_content_warning": "تنشيط تحذير المحتوى", "disable_content_warning": "تعطيل تحذير الحتوى", - "post_visibility_menu": "Post Visibility Menu" + "post_visibility_menu": "قائمة ظهور المنشور" }, "keyboard": { "discard_post": "تجاهُل المنشور", @@ -406,19 +406,19 @@ "relationship_action_alert": { "confirm_unmute_user": { "title": "إلغاء كتم الحساب", - "message": "Confirm to unmute %s" + "message": "أكِّد لرفع كتمْ %s" }, "confirm_unblock_usre": { "title": "إلغاء حظر الحساب", - "message": "Confirm to unblock %s" + "message": "أكِّد لرفع حظر %s" } } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "لا يُمكِن عَرض المُتابِعين مِنَ الخوادم الأُخرى." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "لا يُمكِن عَرض المُتابَعات مِنَ الخوادم الأُخرى." }, "search": { "title": "بحث", @@ -430,7 +430,7 @@ "button_text": "طالع الكل", "hash_tag": { "title": "ذات شعبية على ماستدون", - "description": "Hashtags that are getting quite a bit of attention", + "description": "الوسوم التي تحظى بقدر كبير من الاهتمام", "people_talking": "%s أشخاص يتحدَّثوا" }, "accounts": { @@ -529,11 +529,11 @@ "title": "ابلغ عن %s", "step1": "الخطوة 1 من 2", "step2": "الخطوة 2 من 2", - "content1": "Are there any other posts you’d like to add to the report?", - "content2": "Is there anything the moderators should know about this report?", + "content1": "هل ترغب في إضافة أي مشاركات أُخرى إلى التقرير؟", + "content2": "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذا التقرير؟", "send": "ارسل الشكوى", "skip_to_send": "إرسال بدون تعليق", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "اكتب أو الصق تعليقات إضافيَّة" }, "preview": { "keyboard": { @@ -543,13 +543,13 @@ } }, "account_list": { - "tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher", + "tab_bar_hint": "المِلف المُحدَّد حاليًا: %s. انقر نقرًا مزدوجًا ثم اضغط مع الاستمرار لإظهار مُبدِّل الحِساب", "dismiss_account_switcher": "تجاهُل مبدِّل الحساب", "add_account": "إضافة حساب" }, "wizard": { "new_in_mastodon": "جديد في ماستودون", - "multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.", + "multiple_account_switch_intro_description": "بدِّل بين حسابات متعددة عبر الاستمرار بالضغط على زر الملف الشخصي.", "accessibility_hint": "انقر نقرًا مزدوجًا لتجاهل النافذة المنبثقة" } } From d22ccddbbccb3e702fb792c39982ff0ee11c11cb Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 15 Nov 2021 07:36:18 +0100 Subject: [PATCH 76/87] New translations app.json (Arabic) --- .../StringsConvertor/input/ar_SA/app.json | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Localization/StringsConvertor/input/ar_SA/app.json b/Localization/StringsConvertor/input/ar_SA/app.json index 3e788d6ce..71e0f538f 100644 --- a/Localization/StringsConvertor/input/ar_SA/app.json +++ b/Localization/StringsConvertor/input/ar_SA/app.json @@ -6,21 +6,21 @@ "please_try_again_later": "يُرجى المحاولة مرة أُخرى لاحقاً." }, "sign_up_failure": { - "title": "فشل التسجيل" + "title": "إخفاق في التسجيل" }, "server_error": { "title": "خطأ في الخادم" }, "vote_failure": { - "title": "فشل التصويت", + "title": "إخفاق في التصويت", "poll_ended": "انتهى استطلاع الرأي" }, "discard_post_content": { - "title": "تجاهل المسودة", + "title": "التخلص من المسودة", "message": "أكِّد للتخلص مِن مُحتوى مَنشور مؤلَّف." }, "publish_post_failure": { - "title": "أخفقت عملية النشر", + "title": "إخفاق في عمليَّة النشر", "message": "فَشَلَ نَشر المَنشور.\nيُرجى التحقق من اتصالك بالإنترنت.", "attachments_message": { "video_attach_with_photo": "لا يُمكن إرفاق مقطع مرئي إلى مَنشور يحتوي بالفعل على صُوَر.", @@ -33,19 +33,19 @@ }, "sign_out": { "title": "تسجيل الخروج", - "message": "هل أنت متأكد من أنك تريد تسجيل الخروج؟", + "message": "هل أنت متأكد من رغبتك في تسجيل الخروج؟", "confirm": "تسجيل الخروج" }, "block_domain": { - "title": "Are you really, really sure you want to block the entire %s? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain and any of your followers from that domain will be removed.", - "block_entire_domain": "حظر النطاق" + "title": "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %s بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يتم إزالة جميع متابعيك المتواجدين فيه.", + "block_entire_domain": "حظر النِطاق" }, "save_photo_failure": { - "title": "فشل حفظ الصورة", - "message": "Please enable the photo library access permission to save the photo." + "title": "إخفاق في حفظ الصورة", + "message": "يُرجى إتاحة إذن الوصول إلى مكتبة الصور لحفظ الصورة." }, "delete_post": { - "title": "هل أنت متأكد من أنك تريد حذف هذا المنشور؟", + "title": "هل أنت متأكد من رغبتك في حذف هذا المنشور؟", "delete": "احذف" }, "clean_cache": { @@ -61,7 +61,7 @@ "open": "افتح", "add": "إضافة", "remove": "احذف", - "edit": "تعديل", + "edit": "تحرير", "save": "حفظ", "ok": "حسنًا", "done": "تمّ", @@ -71,21 +71,21 @@ "cancel": "إلغاء", "discard": "تجاهل", "try_again": "المُحاولة مرة أُخرى", - "take_photo": "التقط صورة", + "take_photo": "التقاط صورة", "save_photo": "حفظ الصورة", "copy_photo": "نسخ الصورة", "sign_in": "تسجيل الدخول", "sign_up": "إنشاء حِساب", "see_more": "عرض المزيد", - "preview": "معاينة", - "share": "شارك", - "share_user": "شارك %s", - "share_post": "شارك المنشور", - "open_in_safari": "افتحه في سفاري", + "preview": "مُعاينة", + "share": "المُشارك", + "share_user": "مُشاركة %s", + "share_post": "مشارك المنشور", + "open_in_safari": "الفتح في Safari", "find_people": "ابحث عن أشخاص لمتابعتهم", "manually_search": "البحث يدوياً بدلاً من ذلك", "skip": "تخطي", - "reply": "رد", + "reply": "الرَد", "report_user": "ابلغ عن %s", "block_domain": "حظر %s", "unblock_domain": "إلغاء حظر %s", @@ -130,7 +130,7 @@ "content_warning": "تحذير عن المحتوى", "media_content_warning": "انقر على أي مكان للكشف", "poll": { - "vote": "صَوّت", + "vote": "صَوِّت", "closed": "انتهى" }, "actions": { @@ -181,9 +181,9 @@ "header": { "no_status_found": "لا توجد هناك منشورات", "blocking_warning": "لا يُمكنك الاطلاع على الملف الشخصي لهذا المُستخدِم\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", - "user_blocking_warning": "You can’t view %s’s profile\nuntil you unblock them.\nYour profile looks like this to them.", - "blocked_warning": "You can’t view this user’s profile\nuntil they unblock you.", - "user_blocked_warning": "You can’t view %s’s profile\nuntil they unblock you.", + "user_blocking_warning": "لا يُمكنك الاطلاع على ملف %s الشخصي\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", + "blocked_warning": "لا يُمكِنُكَ عَرض الملف الشخصي لهذا المُستخدِم\nحتَّى يَرفَعَ الحَظر عَنك.", + "user_blocked_warning": "لا يُمكِنُكَ عَرض ملف %s الشخصي\nحتَّى يَرفَعَ الحَظر عَنك.", "suspended_warning": "تمَّ إيقاف هذا المُستخدِم.", "user_suspended_warning": "لقد أوقِفَ حِساب %s." } @@ -450,7 +450,7 @@ "no_results": "ليس هناك أية نتيجة" }, "recent_search": "عمليات البحث الأخيرة", - "clear": "امسح" + "clear": "مَحو" } }, "favorite": { @@ -519,7 +519,7 @@ } }, "footer": { - "mastodon_description": "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء، على غيت هب %s (%s)" + "mastodon_description": "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء على GitHub في %s (%s)" }, "keyboard": { "close_settings_window": "إغلاق نافذة الإعدادات" @@ -529,15 +529,15 @@ "title": "ابلغ عن %s", "step1": "الخطوة 1 من 2", "step2": "الخطوة 2 من 2", - "content1": "هل ترغب في إضافة أي مشاركات أُخرى إلى التقرير؟", - "content2": "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذا التقرير؟", - "send": "ارسل الشكوى", + "content1": "هل ترغب في إضافة أي مشاركات أُخرى إلى الشكوى؟", + "content2": "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذه الشكوى؟", + "send": "إرسال الشكوى", "skip_to_send": "إرسال بدون تعليق", "text_placeholder": "اكتب أو الصق تعليقات إضافيَّة" }, "preview": { "keyboard": { - "close_preview": "إغلاق المعاينة", + "close_preview": "إغلاق المُعايَنَة", "show_next": "إظهار التالي", "show_previous": "إظهار السابق" } From 5916ed4716347f7f665070318ceb5f84e7446b4c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 15 Nov 2021 07:36:19 +0100 Subject: [PATCH 77/87] New translations Localizable.stringsdict (Arabic) --- .../StringsConvertor/input/ar_SA/Localizable.stringsdict | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/ar_SA/Localizable.stringsdict b/Localization/StringsConvertor/input/ar_SA/Localizable.stringsdict index e3dee0d80..0b28c577a 100644 --- a/Localization/StringsConvertor/input/ar_SA/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/ar_SA/Localizable.stringsdict @@ -13,13 +13,13 @@ NSStringFormatValueTypeKey ld zero - %ld unread notification + لا إشعار غير مقروء one إشعار واحِد غير مقروء two إشعاران غير مقروءان few - %ld unread notification + %ld إشعارات غير مقروءة many %ld إشعارًا غيرَ مقروء other @@ -277,7 +277,7 @@ NSStringFormatValueTypeKey ld zero - %ld followers + لا مُتابِع one مُتابِعٌ واحد two From c7632a854e30954320f54ad271e50a69a8eb2791 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 18 Nov 2021 08:44:00 +0100 Subject: [PATCH 78/87] Add note about dual-licensing to Apple to README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e31c4879b..917526711 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,5 @@ The app is compatible with [toot-relay](https://github.com/DagAgren/toot-relay) - [UITextView-Placeholder](https://github.com/devxoul/UITextView-Placeholder) ## License -This project is released under the [GPL-3 License](./LICENSE). + +This project is released under the [GPL-3 License](./LICENSE). It is also dual-licensed to Apple for the purposes of publishing the app on the App Store. For this reason, any contributors are required to sign a Contributor License Agreement. From efbda5a3847622d7588fbb23e114597e815afc2f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Nov 2021 10:22:23 +0100 Subject: [PATCH 79/87] New translations app.json (French) --- Localization/StringsConvertor/input/fr_FR/app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Localization/StringsConvertor/input/fr_FR/app.json b/Localization/StringsConvertor/input/fr_FR/app.json index e27f097e4..74ac01eb2 100644 --- a/Localization/StringsConvertor/input/fr_FR/app.json +++ b/Localization/StringsConvertor/input/fr_FR/app.json @@ -545,7 +545,7 @@ "account_list": { "tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher", "dismiss_account_switcher": "Dismiss Account Switcher", - "add_account": "Add Account" + "add_account": "Ajouter un compte" }, "wizard": { "new_in_mastodon": "New in Mastodon", From fe119641af4dc3590ee645273a058813f0ace7b6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Nov 2021 11:50:16 +0100 Subject: [PATCH 80/87] New translations app.json (French) --- Localization/StringsConvertor/input/fr_FR/app.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Localization/StringsConvertor/input/fr_FR/app.json b/Localization/StringsConvertor/input/fr_FR/app.json index 74ac01eb2..dd834928a 100644 --- a/Localization/StringsConvertor/input/fr_FR/app.json +++ b/Localization/StringsConvertor/input/fr_FR/app.json @@ -415,7 +415,7 @@ } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "Les abonné·e·s issus des autres serveurs ne sont pas affiché·e·s." }, "following": { "footer": "Follows from other servers are not displayed." @@ -548,9 +548,9 @@ "add_account": "Ajouter un compte" }, "wizard": { - "new_in_mastodon": "New in Mastodon", - "multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.", - "accessibility_hint": "Double tap to dismiss this wizard" + "new_in_mastodon": "Nouveau dans Mastodon", + "multiple_account_switch_intro_description": "Basculez entre plusieurs comptes en appuyant de maniere prolongée sur le bouton profil.", + "accessibility_hint": "Tapotez deux fois pour fermer cet assistant" } } } \ No newline at end of file From 3983b94b96e234e58df4de30a8160b35a1c17800 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Nov 2021 11:50:17 +0100 Subject: [PATCH 81/87] New translations Localizable.stringsdict (French) --- .../StringsConvertor/input/fr_FR/Localizable.stringsdict | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict b/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict index d512b204c..4a912e4b3 100644 --- a/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict @@ -13,15 +13,15 @@ NSStringFormatValueTypeKey ld one - 1 unread notification + 1 notification non lue other - %ld unread notification + %ld notifications non lues a11y.plural.count.input_limit_exceeds NSStringLocalizedFormatKey - Input limit exceeds %#@character_count@ + La limite d’entrée dépasse %#@character_count@ character_count NSStringFormatSpecTypeKey From 97f6769a0761ede69f136bf34afa729f9637a749 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 19 Nov 2021 11:50:18 +0100 Subject: [PATCH 82/87] New translations Intents.strings (French) --- .../StringsConvertor/Intents/input/fr_FR/Intents.strings | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings b/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings index 628f794c9..f4fec3000 100644 --- a/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings +++ b/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings @@ -6,7 +6,7 @@ "HZSGTr" = "Quel contenu à publier ?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "Échec lors de la publication"; "KDNTJ4" = "Raison de l’échec"; @@ -40,11 +40,11 @@ "gfePDu" = "Échec lors de la publication. ${failureReason}"; -"k7dbKQ" = "Post was sent successfully."; +"k7dbKQ" = "Message publié avec succès."; -"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; +"oGiqmY-dYQ5NN" = "Juste pour confirmer, vous vouliez « Public » ?"; -"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; +"oGiqmY-ehFLjY" = "Juste pour confirmer, vous vouliez bien diffuser vers « abonné·e·s uniquement » ?"; "rM6dvp" = "URL"; From 4f6890ff01a0490fe166973fe38bb3acb1e0a898 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 3 Dec 2021 19:23:21 +0800 Subject: [PATCH 83/87] chore: deselect iPad target --- Mastodon.xcodeproj/project.pbxproj | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index e5118bf8d..acb82d7a0 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4934,7 +4934,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -4962,7 +4962,7 @@ PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -5227,7 +5227,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -5252,7 +5252,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Debug"; @@ -5277,7 +5277,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Release"; @@ -5302,7 +5302,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -5327,7 +5327,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -5352,7 +5352,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Debug"; @@ -5377,7 +5377,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Release"; @@ -5402,7 +5402,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -5494,7 +5494,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Release"; @@ -5608,7 +5608,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Release"; @@ -5731,7 +5731,7 @@ SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Debug"; @@ -5845,7 +5845,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = "ASDK - Debug"; @@ -5900,7 +5900,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -5924,7 +5924,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; From cb554d6371ca1f734f91e7e66ebf42d371863f54 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 3 Dec 2021 19:26:28 +0800 Subject: [PATCH 84/87] chore: update i18n resources --- .../Resources/ar.lproj/Localizable.strings | 153 +++++++++--------- .../ar.lproj/Localizable.stringsdict | 6 +- .../Resources/fr.lproj/Localizable.strings | 10 +- .../fr.lproj/Localizable.stringsdict | 6 +- MastodonIntent/fr.lproj/Intents.strings | 8 +- 5 files changed, 91 insertions(+), 92 deletions(-) diff --git a/Mastodon/Resources/ar.lproj/Localizable.strings b/Mastodon/Resources/ar.lproj/Localizable.strings index 8681e584d..b878e0342 100644 --- a/Mastodon/Resources/ar.lproj/Localizable.strings +++ b/Mastodon/Resources/ar.lproj/Localizable.strings @@ -1,63 +1,63 @@ -"Common.Alerts.BlockDomain.BlockEntireDomain" = "حظر النطاق"; -"Common.Alerts.BlockDomain.Title" = "Are you really, really sure you want to block the entire %@? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain and any of your followers from that domain will be removed."; +"Common.Alerts.BlockDomain.BlockEntireDomain" = "حظر النِطاق"; +"Common.Alerts.BlockDomain.Title" = "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %@ بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يتم إزالة جميع متابعيك المتواجدين فيه."; "Common.Alerts.CleanCache.Message" = "تمَّ مَحو ذاكرة التخزين المؤقت %@ بنجاح."; "Common.Alerts.CleanCache.Title" = "مَحو ذاكرة التخزين المؤقت"; "Common.Alerts.Common.PleaseTryAgain" = "يُرجى المحاولة مرة أُخرى."; "Common.Alerts.Common.PleaseTryAgainLater" = "يُرجى المحاولة مرة أُخرى لاحقاً."; "Common.Alerts.DeletePost.Delete" = "احذف"; -"Common.Alerts.DeletePost.Title" = "هل أنت متأكد من أنك تريد حذف هذا المنشور؟"; -"Common.Alerts.DiscardPostContent.Message" = "Confirm to discard composed post content."; -"Common.Alerts.DiscardPostContent.Title" = "تجاهل المسودة"; +"Common.Alerts.DeletePost.Title" = "هل أنت متأكد من رغبتك في حذف هذا المنشور؟"; +"Common.Alerts.DiscardPostContent.Message" = "أكِّد للتخلص مِن مُحتوى مَنشور مؤلَّف."; +"Common.Alerts.DiscardPostContent.Title" = "التخلص من المسودة"; "Common.Alerts.EditProfileFailure.Message" = "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى."; "Common.Alerts.EditProfileFailure.Title" = "خطأ في تَحرير الملف الشخصي"; -"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.Message" = "Failed to publish the post. -Please check your internet connection."; -"Common.Alerts.PublishPostFailure.Title" = "أخفقت عملية النشر"; -"Common.Alerts.SavePhotoFailure.Message" = "Please enable the photo library access permission to save the photo."; -"Common.Alerts.SavePhotoFailure.Title" = "فشل حفظ الصورة"; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "لا يُمكِنُ إرفاق أكثر مِن مَقطع مرئي واحِد."; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "لا يُمكن إرفاق مقطع مرئي إلى مَنشور يحتوي بالفعل على صُوَر."; +"Common.Alerts.PublishPostFailure.Message" = "فَشَلَ نَشر المَنشور. +يُرجى التحقق من اتصالك بالإنترنت."; +"Common.Alerts.PublishPostFailure.Title" = "إخفاق في عمليَّة النشر"; +"Common.Alerts.SavePhotoFailure.Message" = "يُرجى إتاحة إذن الوصول إلى مكتبة الصور لحفظ الصورة."; +"Common.Alerts.SavePhotoFailure.Title" = "إخفاق في حفظ الصورة"; "Common.Alerts.ServerError.Title" = "خطأ في الخادم"; "Common.Alerts.SignOut.Confirm" = "تسجيل الخروج"; -"Common.Alerts.SignOut.Message" = "هل أنت متأكد من أنك تريد تسجيل الخروج؟"; +"Common.Alerts.SignOut.Message" = "هل أنت متأكد من رغبتك في تسجيل الخروج؟"; "Common.Alerts.SignOut.Title" = "تسجيل الخروج"; -"Common.Alerts.SignUpFailure.Title" = "فشل التسجيل"; +"Common.Alerts.SignUpFailure.Title" = "إخفاق في التسجيل"; "Common.Alerts.VoteFailure.PollEnded" = "انتهى استطلاع الرأي"; -"Common.Alerts.VoteFailure.Title" = "فشل التصويت"; +"Common.Alerts.VoteFailure.Title" = "إخفاق في التصويت"; "Common.Controls.Actions.Add" = "إضافة"; "Common.Controls.Actions.Back" = "العودة"; "Common.Controls.Actions.BlockDomain" = "حظر %@"; "Common.Controls.Actions.Cancel" = "إلغاء"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "تأليف"; "Common.Controls.Actions.Confirm" = "تأكيد"; "Common.Controls.Actions.Continue" = "واصل"; "Common.Controls.Actions.CopyPhoto" = "نسخ الصورة"; "Common.Controls.Actions.Delete" = "احذف"; "Common.Controls.Actions.Discard" = "تجاهل"; "Common.Controls.Actions.Done" = "تمّ"; -"Common.Controls.Actions.Edit" = "تعديل"; +"Common.Controls.Actions.Edit" = "تحرير"; "Common.Controls.Actions.FindPeople" = "ابحث عن أشخاص لمتابعتهم"; "Common.Controls.Actions.ManuallySearch" = "البحث يدوياً بدلاً من ذلك"; "Common.Controls.Actions.Next" = "التالي"; "Common.Controls.Actions.Ok" = "حسنًا"; "Common.Controls.Actions.Open" = "افتح"; -"Common.Controls.Actions.OpenInSafari" = "افتحه في سفاري"; -"Common.Controls.Actions.Preview" = "معاينة"; +"Common.Controls.Actions.OpenInSafari" = "الفتح في Safari"; +"Common.Controls.Actions.Preview" = "مُعاينة"; "Common.Controls.Actions.Previous" = "السابق"; "Common.Controls.Actions.Remove" = "احذف"; -"Common.Controls.Actions.Reply" = "رد"; +"Common.Controls.Actions.Reply" = "الرَد"; "Common.Controls.Actions.ReportUser" = "ابلغ عن %@"; "Common.Controls.Actions.Save" = "حفظ"; "Common.Controls.Actions.SavePhoto" = "حفظ الصورة"; "Common.Controls.Actions.SeeMore" = "عرض المزيد"; "Common.Controls.Actions.Settings" = "الإعدادات"; -"Common.Controls.Actions.Share" = "شارك"; -"Common.Controls.Actions.SharePost" = "شارك المنشور"; -"Common.Controls.Actions.ShareUser" = "شارك %@"; +"Common.Controls.Actions.Share" = "المُشارك"; +"Common.Controls.Actions.SharePost" = "مشارك المنشور"; +"Common.Controls.Actions.ShareUser" = "مُشاركة %@"; "Common.Controls.Actions.SignIn" = "تسجيل الدخول"; "Common.Controls.Actions.SignUp" = "إنشاء حِساب"; "Common.Controls.Actions.Skip" = "تخطي"; -"Common.Controls.Actions.TakePhoto" = "التقط صورة"; +"Common.Controls.Actions.TakePhoto" = "التقاط صورة"; "Common.Controls.Actions.TryAgain" = "المُحاولة مرة أُخرى"; "Common.Controls.Actions.UnblockDomain" = "إلغاء حظر %@"; "Common.Controls.Friendship.Block" = "حظر"; @@ -76,7 +76,7 @@ Please check your internet connection."; "Common.Controls.Friendship.UnblockUser" = "إلغاء حظر %@"; "Common.Controls.Friendship.Unmute" = "إلغاء الكتم"; "Common.Controls.Friendship.UnmuteUser" = "إلغاء كتم %@"; -"Common.Controls.Keyboard.Common.ComposeNewPost" = "إنشاء منشور جديد"; +"Common.Controls.Keyboard.Common.ComposeNewPost" = "تأليف منشور جديد"; "Common.Controls.Keyboard.Common.OpenSettings" = "أفتح الإعدادات"; "Common.Controls.Keyboard.Common.ShowFavorites" = "إظهار المفضلة"; "Common.Controls.Keyboard.Common.SwitchToTab" = "التبديل إلى %@"; @@ -89,9 +89,9 @@ Please check your internet connection."; "Common.Controls.Keyboard.Timeline.PreviewImage" = "معاينة الصورة"; "Common.Controls.Keyboard.Timeline.PreviousStatus" = "المنشور السابق"; "Common.Controls.Keyboard.Timeline.ReplyStatus" = "رد على المنشور"; -"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Toggle Content Warning"; -"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Toggle Favorite on Post"; -"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Toggle Reblog on Post"; +"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "تبديل تحذير المُحتَوى"; +"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "تبديل المفضلة لِمنشور"; +"Common.Controls.Keyboard.Timeline.ToggleReblog" = "تبديل إعادة تدوين منشور"; "Common.Controls.Status.Actions.Favorite" = "إضافة إلى المفضلة"; "Common.Controls.Status.Actions.Menu" = "القائمة"; "Common.Controls.Status.Actions.Reblog" = "إعادة النشر"; @@ -99,9 +99,9 @@ Please check your internet connection."; "Common.Controls.Status.Actions.Unfavorite" = "إزالة من المفضلة"; "Common.Controls.Status.Actions.Unreblog" = "تراجع عن إعادة النشر"; "Common.Controls.Status.ContentWarning" = "تحذير عن المحتوى"; -"Common.Controls.Status.MediaContentWarning" = "Tap anywhere to reveal"; +"Common.Controls.Status.MediaContentWarning" = "انقر على أي مكان للكشف"; "Common.Controls.Status.Poll.Closed" = "انتهى"; -"Common.Controls.Status.Poll.Vote" = "صَوّت"; +"Common.Controls.Status.Poll.Vote" = "صَوِّت"; "Common.Controls.Status.ShowPost" = "اظهر المنشور"; "Common.Controls.Status.ShowUserProfile" = "اظهر الملف التعريفي للمستخدم"; "Common.Controls.Status.Tag.Email" = "البريد الإلكتروني"; @@ -117,43 +117,42 @@ Please check your internet connection."; "Common.Controls.Tabs.Profile" = "الملف التعريفي"; "Common.Controls.Tabs.Search" = "بحث"; "Common.Controls.Timeline.Filtered" = "مُصفَّى"; -"Common.Controls.Timeline.Header.BlockedWarning" = "You can’t view this user’s profile -until they unblock you."; -"Common.Controls.Timeline.Header.BlockingWarning" = "You can’t view this user's profile -until you unblock them. -Your profile looks like this to them."; +"Common.Controls.Timeline.Header.BlockedWarning" = "لا يُمكِنُكَ عَرض الملف الشخصي لهذا المُستخدِم +حتَّى يَرفَعَ الحَظر عَنك."; +"Common.Controls.Timeline.Header.BlockingWarning" = "لا يُمكنك الاطلاع على الملف الشخصي لهذا المُستخدِم +حتَّى تَرفعَ الحَظر عنه. +ملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا."; "Common.Controls.Timeline.Header.NoStatusFound" = "لا توجد هناك منشورات"; -"Common.Controls.Timeline.Header.SuspendedWarning" = "This user has been suspended."; -"Common.Controls.Timeline.Header.UserBlockedWarning" = "You can’t view %@’s profile -until they unblock you."; -"Common.Controls.Timeline.Header.UserBlockingWarning" = "You can’t view %@’s profile -until you unblock them. -Your profile looks like this to them."; -"Common.Controls.Timeline.Header.UserSuspendedWarning" = "%@’s account has been suspended."; +"Common.Controls.Timeline.Header.SuspendedWarning" = "تمَّ إيقاف هذا المُستخدِم."; +"Common.Controls.Timeline.Header.UserBlockedWarning" = "لا يُمكِنُكَ عَرض ملف %@ الشخصي +حتَّى يَرفَعَ الحَظر عَنك."; +"Common.Controls.Timeline.Header.UserBlockingWarning" = "لا يُمكنك الاطلاع على ملف %@ الشخصي +حتَّى تَرفعَ الحَظر عنه. +ملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا."; +"Common.Controls.Timeline.Header.UserSuspendedWarning" = "لقد أوقِفَ حِساب %@."; "Common.Controls.Timeline.Loader.LoadMissingPosts" = "تحميل المنشورات المَفقودة"; "Common.Controls.Timeline.Loader.LoadingMissingPosts" = "تحميل المزيد من المنشورات..."; "Common.Controls.Timeline.Loader.ShowMoreReplies" = "إظهار المزيد من الردود"; "Common.Controls.Timeline.Timestamp.Now" = "الأن"; "Scene.AccountList.AddAccount" = "إضافة حساب"; "Scene.AccountList.DismissAccountSwitcher" = "تجاهُل مبدِّل الحساب"; -"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher"; +"Scene.AccountList.TabBarHint" = "المِلف المُحدَّد حاليًا: %@. انقر نقرًا مزدوجًا ثم اضغط مع الاستمرار لإظهار مُبدِّل الحِساب"; "Scene.Compose.Accessibility.AppendAttachment" = "إضافة مُرفَق"; "Scene.Compose.Accessibility.AppendPoll" = "اضافة استطلاع رأي"; "Scene.Compose.Accessibility.CustomEmojiPicker" = "منتقي مخصص للإيموجي"; "Scene.Compose.Accessibility.DisableContentWarning" = "تعطيل تحذير الحتوى"; "Scene.Compose.Accessibility.EnableContentWarning" = "تنشيط تحذير المحتوى"; -"Scene.Compose.Accessibility.PostVisibilityMenu" = "Post Visibility Menu"; +"Scene.Compose.Accessibility.PostVisibilityMenu" = "قائمة ظهور المنشور"; "Scene.Compose.Accessibility.RemovePoll" = "إزالة الاستطلاع"; -"Scene.Compose.Attachment.AttachmentBroken" = "This %@ is broken and can’t be -uploaded to Mastodon."; -"Scene.Compose.Attachment.DescriptionPhoto" = "Describe the photo for the visually-impaired..."; -"Scene.Compose.Attachment.DescriptionVideo" = "Describe the video for the visually-impaired..."; +"Scene.Compose.Attachment.AttachmentBroken" = "هذا ال%@ مُعطَّل ويتعذَّر رفعه إلى ماستودون."; +"Scene.Compose.Attachment.DescriptionPhoto" = "صِف الصورة للمكفوفين..."; +"Scene.Compose.Attachment.DescriptionVideo" = "صِف المقطع المرئي للمكفوفين..."; "Scene.Compose.Attachment.Photo" = "صورة"; "Scene.Compose.Attachment.Video" = "فيديو"; -"Scene.Compose.AutoComplete.SpaceToAdd" = "Space to add"; +"Scene.Compose.AutoComplete.SpaceToAdd" = "انقر مساحة لإضافتِها"; "Scene.Compose.ComposeAction" = "انشر"; "Scene.Compose.ContentInputPlaceholder" = "أخبِرنا بِما يَجُولُ فِي ذِهنَك"; -"Scene.Compose.ContentWarning.Placeholder" = "Write an accurate warning here..."; +"Scene.Compose.ContentWarning.Placeholder" = "اكتب تَحذيرًا دَقيقًا هُنا..."; "Scene.Compose.Keyboard.AppendAttachmentEntry" = "إضافة مُرفَق - %@"; "Scene.Compose.Keyboard.DiscardPost" = "تجاهُل المنشور"; "Scene.Compose.Keyboard.PublishPost" = "نَشر المَنشُور"; @@ -180,10 +179,10 @@ uploaded to Mastodon."; "Scene.Compose.Visibility.Unlisted" = "غير مُدرَج"; "Scene.ConfirmEmail.Button.DontReceiveEmail" = "لم أستلم أبدًا بريدا إلكترونيا"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "افتح تطبيق البريد الإلكتروني"; -"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Check if your email address is correct as well as your junk folder if you haven’t."; +"Scene.ConfirmEmail.DontReceiveEmail.Description" = "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "إعادة إرسال البريد الإلكتروني"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "تحقق من بريدك الإلكتروني"; -"Scene.ConfirmEmail.OpenEmailApp.Description" = "We just sent you an email. Check your junk folder if you haven’t."; +"Scene.ConfirmEmail.OpenEmailApp.Description" = "لقد أرسلنا لك بريدًا إلكترونيًا للتو. تحقق من مجلد البريد غير الهام الخاص بك إذا لم تكن قد فعلت ذلك."; "Scene.ConfirmEmail.OpenEmailApp.Mail" = "البريد"; "Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "فتح عميل البريد الإلكتروني"; "Scene.ConfirmEmail.OpenEmailApp.Title" = "تحقَّق من بريدك الوارِد."; @@ -191,8 +190,8 @@ uploaded to Mastodon."; اضغط على الرابط لتأكيد حسابك."; "Scene.ConfirmEmail.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.Follower.Footer" = "لا يُمكِن عَرض المُتابِعين مِنَ الخوادم الأُخرى."; +"Scene.Following.Footer" = "لا يُمكِن عَرض المُتابَعات مِنَ الخوادم الأُخرى."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "إظهار منشورات جديدة"; "Scene.HomeTimeline.NavigationBarState.Offline" = "غير متصل"; "Scene.HomeTimeline.NavigationBarState.Published" = "تم نشره!"; @@ -208,7 +207,7 @@ uploaded to Mastodon."; "Scene.Notification.UserRebloggedYourPost" = "أعاد %@ تدوين مشاركتك"; "Scene.Notification.UserRequestedToFollowYou" = "طلب %@ متابعتك"; "Scene.Notification.UserYourPollHasEnded" = "%@ اِنتهى استطلاعُكَ للرأي"; -"Scene.Preview.Keyboard.ClosePreview" = "إغلاق المعاينة"; +"Scene.Preview.Keyboard.ClosePreview" = "إغلاق المُعايَنَة"; "Scene.Preview.Keyboard.ShowNext" = "إظهار التالي"; "Scene.Preview.Keyboard.ShowPrevious" = "إظهار السابق"; "Scene.Profile.Dashboard.Followers" = "متابِع"; @@ -217,9 +216,9 @@ uploaded to Mastodon."; "Scene.Profile.Fields.AddRow" = "إضافة صف"; "Scene.Profile.Fields.Placeholder.Content" = "المحتوى"; "Scene.Profile.Fields.Placeholder.Label" = "التسمية"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirm to unblock %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "أكِّد لرفع حظر %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "إلغاء حظر الحساب"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Confirm to unmute %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "أكِّد لرفع كتمْ %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "إلغاء كتم الحساب"; "Scene.Profile.SegmentedControl.Media" = "وسائط"; "Scene.Profile.SegmentedControl.Posts" = "منشورات"; @@ -230,20 +229,20 @@ uploaded to Mastodon."; "Scene.Register.Error.Item.Password" = "الكلمة السرية"; "Scene.Register.Error.Item.Reason" = "السبب"; "Scene.Register.Error.Item.Username" = "اسم المستخدم"; -"Scene.Register.Error.Reason.Accepted" = "%@ must be accepted"; +"Scene.Register.Error.Reason.Accepted" = "يجب أن يُقبل %@"; "Scene.Register.Error.Reason.Blank" = "%@ مطلوب"; -"Scene.Register.Error.Reason.Blocked" = "%@ contains a disallowed email provider"; -"Scene.Register.Error.Reason.Inclusion" = "%@ is not a supported value"; +"Scene.Register.Error.Reason.Blocked" = "يحتوي %@ على موفِّر خدمة بريد إلكتروني غير مسموح به"; +"Scene.Register.Error.Reason.Inclusion" = "إنَّ %@ قيمة غير مدعومة"; "Scene.Register.Error.Reason.Invalid" = "%@ غير صالح"; -"Scene.Register.Error.Reason.Reserved" = "%@ is a reserved keyword"; -"Scene.Register.Error.Reason.Taken" = "%@ is already in use"; +"Scene.Register.Error.Reason.Reserved" = "إنَّ %@ عبارة عن كلمة مفتاحيَّة محجوزة"; +"Scene.Register.Error.Reason.Taken" = "إنَّ %@ مُستخدَمٌ بالفعل"; "Scene.Register.Error.Reason.TooLong" = "%@ طويل جداً"; "Scene.Register.Error.Reason.TooShort" = "%@ قصير جدا"; -"Scene.Register.Error.Reason.Unreachable" = "%@ does not seem to exist"; +"Scene.Register.Error.Reason.Unreachable" = "يبدوا أنَّ %@ غير موجود"; "Scene.Register.Error.Special.EmailInvalid" = "هذا عنوان بريد إلكتروني غير صالح"; "Scene.Register.Error.Special.PasswordTooShort" = "كلمة المرور قصيرة جداً (يجب أن تكون 8 أحرف على الأقل)"; -"Scene.Register.Error.Special.UsernameInvalid" = "Username must only contain alphanumeric characters and underscores"; -"Scene.Register.Error.Special.UsernameTooLong" = "Username is too long (can’t be longer than 30 characters)"; +"Scene.Register.Error.Special.UsernameInvalid" = "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط"; +"Scene.Register.Error.Special.UsernameTooLong" = "اسم المستخدم طويل جداً (يجب ألّا يكون أطول من 30 رمز)"; "Scene.Register.Input.Avatar.Delete" = "احذف"; "Scene.Register.Input.DisplayName.Placeholder" = "الاسم المعروض"; "Scene.Register.Input.Email.Placeholder" = "البريد الإلكتروني"; @@ -253,24 +252,24 @@ uploaded to Mastodon."; "Scene.Register.Input.Username.DuplicatePrompt" = "اسم المستخدم هذا غير متوفر."; "Scene.Register.Input.Username.Placeholder" = "اسم المستخدم"; "Scene.Register.Title" = "أخبرنا عنك."; -"Scene.Report.Content1" = "Are there any other posts you’d like to add to the report?"; -"Scene.Report.Content2" = "Is there anything the moderators should know about this report?"; -"Scene.Report.Send" = "ارسل الشكوى"; +"Scene.Report.Content1" = "هل ترغب في إضافة أي مشاركات أُخرى إلى الشكوى؟"; +"Scene.Report.Content2" = "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذه الشكوى؟"; +"Scene.Report.Send" = "إرسال الشكوى"; "Scene.Report.SkipToSend" = "إرسال بدون تعليق"; "Scene.Report.Step1" = "الخطوة 1 من 2"; "Scene.Report.Step2" = "الخطوة 2 من 2"; -"Scene.Report.TextPlaceholder" = "Type or paste additional comments"; +"Scene.Report.TextPlaceholder" = "اكتب أو الصق تعليقات إضافيَّة"; "Scene.Report.Title" = "ابلغ عن %@"; "Scene.Search.Recommend.Accounts.Description" = "قد ترغب في متابعة هذه الحسابات"; "Scene.Search.Recommend.Accounts.Follow" = "تابع"; "Scene.Search.Recommend.Accounts.Title" = "حسابات قد تعجبك"; "Scene.Search.Recommend.ButtonText" = "طالع الكل"; -"Scene.Search.Recommend.HashTag.Description" = "Hashtags that are getting quite a bit of attention"; +"Scene.Search.Recommend.HashTag.Description" = "الوسوم التي تحظى بقدر كبير من الاهتمام"; "Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ أشخاص يتحدَّثوا"; "Scene.Search.Recommend.HashTag.Title" = "ذات شعبية على ماستدون"; "Scene.Search.SearchBar.Cancel" = "إلغاء"; "Scene.Search.SearchBar.Placeholder" = "البحث عن وسوم أو مستخدمين·ات"; -"Scene.Search.Searching.Clear" = "امسح"; +"Scene.Search.Searching.Clear" = "مَحو"; "Scene.Search.Searching.EmptyState.NoResults" = "ليس هناك أية نتيجة"; "Scene.Search.Searching.RecentSearch" = "عمليات البحث الأخيرة"; "Scene.Search.Searching.Segment.All" = "الكل"; @@ -294,7 +293,7 @@ uploaded to Mastodon."; "Scene.ServerPicker.Button.Category.Tech" = "تكنولوجيا"; "Scene.ServerPicker.Button.SeeLess" = "اعرض أقل"; "Scene.ServerPicker.Button.SeeMore" = "اعرض المزيد"; -"Scene.ServerPicker.EmptyState.BadNetwork" = "Something went wrong while loading the data. Check your internet connection."; +"Scene.ServerPicker.EmptyState.BadNetwork" = "حدث خطأٌ ما أثناء تحميل البيانات. تحقَّق من اتصالك بالإنترنت."; "Scene.ServerPicker.EmptyState.FindingServers" = "البحث عن خوادم متوفرة..."; "Scene.ServerPicker.EmptyState.NoResults" = "لا توجد نتائج"; "Scene.ServerPicker.Input.Placeholder" = "ابحث عن خادم أو انضم إلى سيرفر خاص بك..."; @@ -309,7 +308,7 @@ uploaded to Mastodon."; "Scene.ServerRules.Subtitle" = "تم سنّ هذه القواعد من قبل مشرفي %@."; "Scene.ServerRules.TermsOfService" = "شروط الخدمة"; "Scene.ServerRules.Title" = "بعض القواعد الأساسية."; -"Scene.Settings.Footer.MastodonDescription" = "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء، على غيت هب %@ (%@)"; +"Scene.Settings.Footer.MastodonDescription" = "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء على GitHub في %@ (%@)"; "Scene.Settings.Keyboard.CloseSettingsWindow" = "إغلاق نافذة الإعدادات"; "Scene.Settings.Section.Appearance.Automatic" = "تلقائي"; "Scene.Settings.Section.Appearance.Dark" = "مظلمٌ دائِمًا"; @@ -338,12 +337,12 @@ uploaded to Mastodon."; "Scene.Settings.Section.SpicyZone.Signout" = "تسجيل الخروج"; "Scene.Settings.Section.SpicyZone.Title" = "المنطقة الحارة"; "Scene.Settings.Title" = "الإعدادات"; -"Scene.SuggestionAccount.FollowExplain" = "When you follow someone, you’ll see their posts in your home feed."; +"Scene.SuggestionAccount.FollowExplain" = "عِندَ مُتابَعَتِكَ لأحدِهِم، سَوف تَرى مَنشوراته في تغذيَتِكَ الرئيسة."; "Scene.SuggestionAccount.Title" = "ابحث عن أشخاص لمتابعتهم"; "Scene.Thread.BackTitle" = "منشور"; "Scene.Thread.Title" = "مَنشور مِن %@"; -"Scene.Welcome.Slogan" = "Social networking -back in your hands."; +"Scene.Welcome.Slogan" = "شبكات التواصل الاجتماعي +مرة أُخرى بين يديك."; "Scene.Wizard.AccessibilityHint" = "انقر نقرًا مزدوجًا لتجاهل النافذة المنبثقة"; -"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button."; +"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "بدِّل بين حسابات متعددة عبر الاستمرار بالضغط على زر الملف الشخصي."; "Scene.Wizard.NewInMastodon" = "جديد في ماستودون"; \ No newline at end of file diff --git a/Mastodon/Resources/ar.lproj/Localizable.stringsdict b/Mastodon/Resources/ar.lproj/Localizable.stringsdict index e3dee0d80..0b28c577a 100644 --- a/Mastodon/Resources/ar.lproj/Localizable.stringsdict +++ b/Mastodon/Resources/ar.lproj/Localizable.stringsdict @@ -13,13 +13,13 @@ NSStringFormatValueTypeKey ld zero - %ld unread notification + لا إشعار غير مقروء one إشعار واحِد غير مقروء two إشعاران غير مقروءان few - %ld unread notification + %ld إشعارات غير مقروءة many %ld إشعارًا غيرَ مقروء other @@ -277,7 +277,7 @@ NSStringFormatValueTypeKey ld zero - %ld followers + لا مُتابِع one مُتابِعٌ واحد two diff --git a/Mastodon/Resources/fr.lproj/Localizable.strings b/Mastodon/Resources/fr.lproj/Localizable.strings index 9514a7a5e..a4dbfdb6f 100644 --- a/Mastodon/Resources/fr.lproj/Localizable.strings +++ b/Mastodon/Resources/fr.lproj/Localizable.strings @@ -134,7 +134,7 @@ Votre profil ressemble à ça pour lui."; "Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Chargement des publications manquantes..."; "Common.Controls.Timeline.Loader.ShowMoreReplies" = "Charger plus de réponses"; "Common.Controls.Timeline.Timestamp.Now" = "À l’instant"; -"Scene.AccountList.AddAccount" = "Add Account"; +"Scene.AccountList.AddAccount" = "Ajouter un compte"; "Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher"; "Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher"; "Scene.Compose.Accessibility.AppendAttachment" = "Joindre un document"; @@ -191,7 +191,7 @@ téléversé sur Mastodon."; tapotez le lien pour confirmer votre compte."; "Scene.ConfirmEmail.Title" = "Une dernière chose."; "Scene.Favorite.Title" = "Vos favoris"; -"Scene.Follower.Footer" = "Followers from other servers are not displayed."; +"Scene.Follower.Footer" = "Les abonné·e·s issus des autres serveurs ne sont pas affiché·e·s."; "Scene.Following.Footer" = "Follows from other servers are not displayed."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "Voir les nouvelles publications"; "Scene.HomeTimeline.NavigationBarState.Offline" = "Hors ligne"; @@ -343,6 +343,6 @@ n'importe quel serveur."; "Scene.Thread.BackTitle" = "Publication"; "Scene.Thread.Title" = "Publication de %@"; "Scene.Welcome.Slogan" = "Le réseau social qui vous rend le contrôle."; -"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; -"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button."; -"Scene.Wizard.NewInMastodon" = "New in Mastodon"; \ No newline at end of file +"Scene.Wizard.AccessibilityHint" = "Tapotez deux fois pour fermer cet assistant"; +"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Basculez entre plusieurs comptes en appuyant de maniere prolongée sur le bouton profil."; +"Scene.Wizard.NewInMastodon" = "Nouveau dans Mastodon"; \ No newline at end of file diff --git a/Mastodon/Resources/fr.lproj/Localizable.stringsdict b/Mastodon/Resources/fr.lproj/Localizable.stringsdict index d512b204c..4a912e4b3 100644 --- a/Mastodon/Resources/fr.lproj/Localizable.stringsdict +++ b/Mastodon/Resources/fr.lproj/Localizable.stringsdict @@ -13,15 +13,15 @@ NSStringFormatValueTypeKey ld one - 1 unread notification + 1 notification non lue other - %ld unread notification + %ld notifications non lues a11y.plural.count.input_limit_exceeds NSStringLocalizedFormatKey - Input limit exceeds %#@character_count@ + La limite d’entrée dépasse %#@character_count@ character_count NSStringFormatSpecTypeKey diff --git a/MastodonIntent/fr.lproj/Intents.strings b/MastodonIntent/fr.lproj/Intents.strings index 628f794c9..f4fec3000 100644 --- a/MastodonIntent/fr.lproj/Intents.strings +++ b/MastodonIntent/fr.lproj/Intents.strings @@ -6,7 +6,7 @@ "HZSGTr" = "Quel contenu à publier ?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "Échec lors de la publication"; "KDNTJ4" = "Raison de l’échec"; @@ -40,11 +40,11 @@ "gfePDu" = "Échec lors de la publication. ${failureReason}"; -"k7dbKQ" = "Post was sent successfully."; +"k7dbKQ" = "Message publié avec succès."; -"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; +"oGiqmY-dYQ5NN" = "Juste pour confirmer, vous vouliez « Public » ?"; -"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; +"oGiqmY-ehFLjY" = "Juste pour confirmer, vous vouliez bien diffuser vers « abonné·e·s uniquement » ?"; "rM6dvp" = "URL"; From 7859ebd4ffb674d4157fb81fe0c627c27fbeb818 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 3 Dec 2021 19:28:50 +0800 Subject: [PATCH 85/87] chore: add "Open in Browser" i18n word. #307 --- Localization/app.json | 1 + 1 file changed, 1 insertion(+) diff --git a/Localization/app.json b/Localization/app.json index 5c01ae7e0..6d3b2fcc2 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", From 079792784cbcbac2db87a14c1e662e8db41fe540 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 3 Dec 2021 20:23:40 +0800 Subject: [PATCH 86/87] feat: patch some VoiceOver issues. #309 --- .../xcschemes/xcschememanagement.plist | 8 +++--- .../Section/Status/NotificationSection.swift | 28 +++++++++++++++++++ .../Section/Status/PollSection.swift | 9 ++++++ .../Section/Status/StatusSection.swift | 8 +++++- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index aa6a21a4c..913a8fdb7 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 47 + 37 CoreDataStack.xcscheme_^#shared#^_ orderHint - 46 + 36 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 45 + 38 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 48 + 39 SuppressBuildableAutocreation diff --git a/Mastodon/Diffiable/Section/Status/NotificationSection.swift b/Mastodon/Diffiable/Section/Status/NotificationSection.swift index 22283a479..864785007 100644 --- a/Mastodon/Diffiable/Section/Status/NotificationSection.swift +++ b/Mastodon/Diffiable/Section/Status/NotificationSection.swift @@ -45,6 +45,8 @@ extension NotificationSection { attribute: attribute ) cell.delegate = delegate + cell.isAccessibilityElement = true + NotificationSection.configureStatusAccessibilityLabel(cell: cell) return cell case .notificationStatus(objectID: let objectID, attribute: let attribute): @@ -215,4 +217,30 @@ extension NotificationSection { cell.containerStackViewBottomLayoutConstraint.constant = 5 // 5pt margin when no status view } } + + static func configureStatusAccessibilityLabel(cell: NotificationStatusTableViewCell) { + // FIXME: + cell.accessibilityLabel = { + var accessibilityViews: [UIView?] = [] + accessibilityViews.append(contentsOf: [ + cell.titleLabel, + cell.timestampLabel, + cell.statusView + ]) + if !cell.statusContainerView.isHidden { + if !cell.statusView.headerContainerView.isHidden { + accessibilityViews.append(cell.statusView.headerInfoLabel) + } + accessibilityViews.append(contentsOf: [ + cell.statusView.nameMetaLabel, + cell.statusView.dateLabel, + cell.statusView.contentMetaText.textView, + ]) + } + return accessibilityViews + .compactMap { $0?.accessibilityLabel } + .joined(separator: " ") + }() + } } + diff --git a/Mastodon/Diffiable/Section/Status/PollSection.swift b/Mastodon/Diffiable/Section/Status/PollSection.swift index add2a79b2..682a2abc0 100644 --- a/Mastodon/Diffiable/Section/Status/PollSection.swift +++ b/Mastodon/Diffiable/Section/Status/PollSection.swift @@ -37,6 +37,15 @@ extension PollSection { managedObjectContext.performAndWait { let option = managedObjectContext.object(with: objectID) as! PollOption PollSection.configure(cell: cell, pollOption: option, pollItemAttribute: attribute) + + cell.isAccessibilityElement = true + cell.accessibilityLabel = { + var labels: [String] = [option.title] + if let percentage = cell.pollOptionView.optionPercentageLabel.text { + labels.append(percentage) + } + return labels.joined(separator: ",") + }() } return cell } diff --git a/Mastodon/Diffiable/Section/Status/StatusSection.swift b/Mastodon/Diffiable/Section/Status/StatusSection.swift index ceb0c9458..61217c790 100644 --- a/Mastodon/Diffiable/Section/Status/StatusSection.swift +++ b/Mastodon/Diffiable/Section/Status/StatusSection.swift @@ -158,6 +158,11 @@ extension StatusSection { accessibilityElements.append(cell.statusView.avatarView) accessibilityElements.append(cell.statusView.nameMetaLabel) accessibilityElements.append(cell.statusView.dateLabel) + // poll + accessibilityElements.append(cell.statusView.pollTableView) + accessibilityElements.append(cell.statusView.pollVoteCountLabel) + accessibilityElements.append(cell.statusView.pollCountdownLabel) + accessibilityElements.append(cell.statusView.pollVoteButton) // TODO: a11y accessibilityElements.append(cell.statusView.contentMetaText.textView) accessibilityElements.append(contentsOf: cell.statusView.statusMosaicImageViewContainer.imageViews) @@ -389,7 +394,7 @@ extension StatusSection { // set timestamp let createdAt = (status.reblog ?? status).createdAt cell.statusView.dateLabel.text = createdAt.localizedSlowedTimeAgoSinceNow - cell.statusView.dateLabel.accessibilityValue = createdAt.timeAgoSinceNow + cell.statusView.dateLabel.accessibilityLabel = createdAt.timeAgoSinceNow AppContext.shared.timestampUpdatePublisher .receive(on: RunLoop.main) // will be paused when scrolling (on purpose) .sink { [weak cell] _ in @@ -978,6 +983,7 @@ extension StatusSection { cell.statusView.pollCountdownLabel.text = "-" } + cell.statusView.isUserInteractionEnabled = !poll.expired // make voice over touch passthroughable cell.statusView.pollTableView.allowsSelection = !poll.expired let votedOptions = poll.options.filter { option in From 15506171108617d8c161e5ae388b47640e0f2462 Mon Sep 17 00:00:00 2001 From: CMK Date: Fri, 3 Dec 2021 20:29:25 +0800 Subject: [PATCH 87/87] chore: update version to 1.2.0 (88) --- AppShared/Info.plist | 2 +- CoreDataStack/Info.plist | 2 +- CoreDataStackTests/Info.plist | 2 +- Mastodon.xcodeproj/project.pbxproj | 64 +++++++++---------- .../xcschemes/xcschememanagement.plist | 8 +-- Mastodon/Info.plist | 2 +- MastodonIntent/Info.plist | 2 +- MastodonTests/Info.plist | 2 +- MastodonUITests/Info.plist | 2 +- NotificationService/Info.plist | 2 +- ShareActionExtension/Info.plist | 2 +- 11 files changed, 45 insertions(+), 45 deletions(-) diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 9e3842757..9fe845c60 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 diff --git a/CoreDataStack/Info.plist b/CoreDataStack/Info.plist index 9e3842757..9fe845c60 100644 --- a/CoreDataStack/Info.plist +++ b/CoreDataStack/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 diff --git a/CoreDataStackTests/Info.plist b/CoreDataStackTests/Info.plist index 9e3842757..9fe845c60 100644 --- a/CoreDataStackTests/Info.plist +++ b/CoreDataStackTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index acb82d7a0..6b7644e3e 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4919,7 +4919,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4948,7 +4948,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5056,11 +5056,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5087,11 +5087,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5116,11 +5116,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5146,11 +5146,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5213,7 +5213,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5238,7 +5238,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5263,7 +5263,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5288,7 +5288,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5313,7 +5313,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5338,7 +5338,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5363,7 +5363,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5388,7 +5388,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5479,7 +5479,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5546,11 +5546,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5595,7 +5595,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5620,11 +5620,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5716,7 +5716,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5783,11 +5783,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = CoreDataStack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5832,7 +5832,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5857,11 +5857,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 87; + DYLIB_CURRENT_VERSION = 88; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5887,7 +5887,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5911,7 +5911,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 87; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 913a8fdb7..5c99e944b 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 37 + 44 CoreDataStack.xcscheme_^#shared#^_ orderHint - 36 + 45 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -102,7 +102,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 38 + 43 MastodonIntents.xcscheme_^#shared#^_ @@ -122,7 +122,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 39 + 42 SuppressBuildableAutocreation diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index 00bab8799..affa5b059 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 87 + 88 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index 986b62577..8ac3d165b 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 NSExtension NSExtensionAttributes diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 9e3842757..9fe845c60 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 9e3842757..9fe845c60 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index a6cdb01a1..8e14f3a2a 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index b5052eb9e..1b3025474 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.2.0 CFBundleVersion - 87 + 88 NSExtension NSExtensionAttributes