diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 3d06762c8..21baf4a3e 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleVersion - 140 + 144 diff --git a/Localization/StringsConvertor/input/ar.lproj/app.json b/Localization/StringsConvertor/input/ar.lproj/app.json index ab8eba9dc..732b5acb2 100644 --- a/Localization/StringsConvertor/input/ar.lproj/app.json +++ b/Localization/StringsConvertor/input/ar.lproj/app.json @@ -2,18 +2,18 @@ "common": { "alerts": { "common": { - "please_try_again": "يُرجى المُحاولة مرة أُخرى.", + "please_try_again": "يُرجى المُحاوَلَةُ مُجَدَّدًا.", "please_try_again_later": "يُرجى المُحاولة مرة أُخرى لاحقًا." }, "sign_up_failure": { - "title": "إخفاق في التسجيل" + "title": "إخفاقٌ فِي التَّسجيل" }, "server_error": { - "title": "خطأ في الخادم" + "title": "خَطَأٌ فِي الخادِم" }, "vote_failure": { - "title": "إخفاق في التصويت", - "poll_ended": "انتهى استطلاع الرأي" + "title": "إخفاقٌ فِي التَّصويت", + "poll_ended": "اِنتَهَى اِستِطلاعُ الرَّأي" }, "discard_post_content": { "title": "التخلص من المسودة", @@ -216,26 +216,26 @@ "subtitle_extend": "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام. تُشغَّل جميعُ المجتمعِ مِن قِبَلِ مُنظمَةٍ أو فردٍ مُستقلٍ تمامًا.", "button": { "category": { - "all": "الكل", - "all_accessiblity_description": "الفئة: الكل", + "all": "الكُل", + "all_accessiblity_description": "الفِئَة: الكُل", "academia": "أكاديمي", - "activism": "النشطاء", - "food": "الطعام", - "furry": "مكسو بالفرو", - "games": "ألعاب", - "general": "عام", - "journalism": "صحافة", - "lgbt": "مجتمع الشواذ", + "activism": "نُشَطاء", + "food": "طَعام", + "furry": "مَكسُوٌ بِالفَرو", + "games": "ألعَاب", + "general": "عَام", + "journalism": "صَحافة", + "lgbt": "مَخَانِيث", "regional": "إقليمي", - "art": "فنون", - "music": "موسيقى", - "tech": "تقنية" + "art": "فُنون", + "music": "مُوسيقى", + "tech": "تَقنِيَة" }, - "see_less": "عرض عناصر أقل", - "see_more": "عرض عناصر أكثر" + "see_less": "عَرضُ عَناصِرٍ أقَل", + "see_more": "عَرضُ عَناصِرٍ أكثَر" }, "label": { - "language": "اللُّغة", + "language": "اللُّغَة", "users": "مُستَخدِم", "category": "الفئة" }, @@ -286,8 +286,8 @@ "email": "البريد الإلكتروني", "password": "الرمز السري", "agreement": "الاِتِّفاقيَّة", - "locale": "اللغة المحلية", - "reason": "السبب" + "locale": "اللُّغَة", + "reason": "السَّبَب" }, "reason": { "blocked": "يحتوي %s على موفِّر خدمة بريد إلكتروني غير مسموح به", @@ -297,14 +297,14 @@ "accepted": "يجب أن يُقبل %s", "blank": "%s مَطلوب", "invalid": "%s غير صالح", - "too_long": "%s طويل جداً", - "too_short": "%s قصير جدًا", + "too_long": "%s طَويلٌ جِدًّا", + "too_short": "%s قَصِيرٌ جِدًا", "inclusion": "إنَّ %s قيمة غير مدعومة" }, "special": { "username_invalid": "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط", "username_too_long": "اِسم المُستَخدِم طويل جداً (يَجِبُ ألّا يكون أطول من ثلاثين خانة)", - "email_invalid": "هذا عنوان بريد إلكتروني غير صالح", + "email_invalid": "عُنوانُ البَريدِ الاِلِكتُرُونيّ هَذَا غَيرُ صَالِح", "password_too_short": "رمز السر قصير جدًا (يجب أن يتكون من ثمان خانات على الأقل)" } } @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "أظْهِر كُلَّ شَيء", "show_mentions": "أظْهِر الإشارَات" + }, + "follow_request": { + "accept": "قَبُول", + "accepted": "مَقبُول", + "reject": "رَفض", + "rejected": "مَرفُوض" } }, "thread": { diff --git a/Localization/StringsConvertor/input/ca.lproj/app.json b/Localization/StringsConvertor/input/ca.lproj/app.json index d42d470b5..da78cf285 100644 --- a/Localization/StringsConvertor/input/ca.lproj/app.json +++ b/Localization/StringsConvertor/input/ca.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Mostrar-ho tot", "show_mentions": "Mostrar Mencions" + }, + "follow_request": { + "accept": "Acceptar", + "accepted": "Acceptat", + "reject": "rebutjar", + "rejected": "Rebutjat" } }, "thread": { diff --git a/Localization/StringsConvertor/input/ckb.lproj/app.json b/Localization/StringsConvertor/input/ckb.lproj/app.json index 9f60b2cb0..926590d74 100644 --- a/Localization/StringsConvertor/input/ckb.lproj/app.json +++ b/Localization/StringsConvertor/input/ckb.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "هەموو شتێک نیشان بدە", "show_mentions": "ئاماژەکان نیشان بدە" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/cy.lproj/app.json b/Localization/StringsConvertor/input/cy.lproj/app.json index d1c4f7d98..710f42b93 100644 --- a/Localization/StringsConvertor/input/cy.lproj/app.json +++ b/Localization/StringsConvertor/input/cy.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/da.lproj/app.json b/Localization/StringsConvertor/input/da.lproj/app.json index 93c3f9955..a965b23ae 100644 --- a/Localization/StringsConvertor/input/da.lproj/app.json +++ b/Localization/StringsConvertor/input/da.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/de.lproj/app.json b/Localization/StringsConvertor/input/de.lproj/app.json index ebcab3d18..1633a7aba 100644 --- a/Localization/StringsConvertor/input/de.lproj/app.json +++ b/Localization/StringsConvertor/input/de.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Alles anzeigen", "show_mentions": "Erwähnungen anzeigen" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/en-US.lproj/app.json b/Localization/StringsConvertor/input/en-US.lproj/app.json index 93c3f9955..a965b23ae 100644 --- a/Localization/StringsConvertor/input/en-US.lproj/app.json +++ b/Localization/StringsConvertor/input/en-US.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/en.lproj/app.json b/Localization/StringsConvertor/input/en.lproj/app.json index 93c3f9955..a965b23ae 100644 --- a/Localization/StringsConvertor/input/en.lproj/app.json +++ b/Localization/StringsConvertor/input/en.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/es-AR.lproj/app.json b/Localization/StringsConvertor/input/es-AR.lproj/app.json index b218aeb86..9b9f8de5a 100644 --- a/Localization/StringsConvertor/input/es-AR.lproj/app.json +++ b/Localization/StringsConvertor/input/es-AR.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Mostrar todo", "show_mentions": "Mostrar menciones" + }, + "follow_request": { + "accept": "Aceptar", + "accepted": "Aceptada", + "reject": "rechazar", + "rejected": "Rechazada" } }, "thread": { diff --git a/Localization/StringsConvertor/input/es.lproj/Localizable.stringsdict b/Localization/StringsConvertor/input/es.lproj/Localizable.stringsdict index 05bcff142..def3d7bba 100644 --- a/Localization/StringsConvertor/input/es.lproj/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/es.lproj/Localizable.stringsdict @@ -72,9 +72,9 @@ NSStringFormatValueTypeKey ld one - Followed by %1$@, and another mutual + Seguido por %1$@ y otro mutuo other - Followed by %1$@, and %ld mutuals + Seguido por %1$@ y %ld mutuos plural.count.metric_formatted.post diff --git a/Localization/StringsConvertor/input/es.lproj/app.json b/Localization/StringsConvertor/input/es.lproj/app.json index 3f4666685..a6d0225d3 100644 --- a/Localization/StringsConvertor/input/es.lproj/app.json +++ b/Localization/StringsConvertor/input/es.lproj/app.json @@ -129,7 +129,7 @@ "show_post": "Mostrar Publicación", "show_user_profile": "Mostrar perfil del usuario", "content_warning": "Advertencia de Contenido", - "sensitive_content": "Sensitive Content", + "sensitive_content": "Contenido sensible", "media_content_warning": "Pulsa en cualquier sitio para mostrar", "tap_to_reveal": "Tocar para revelar", "poll": { @@ -241,7 +241,7 @@ }, "input": { "placeholder": "Encuentra un servidor o únete al tuyo propio...", - "search_servers_or_enter_url": "Search servers or enter URL" + "search_servers_or_enter_url": "Buscar servidores o introducir la URL" }, "empty_state": { "finding_servers": "Encontrando servidores disponibles...", @@ -251,7 +251,7 @@ }, "register": { "title": "Háblanos de ti.", - "lets_get_you_set_up_on_domain": "Let’s get you set up on %s", + "lets_get_you_set_up_on_domain": "Deja que te preparemos en %s", "input": { "avatar": { "delete": "Borrar" @@ -322,7 +322,7 @@ "confirm_email": { "title": "Una última cosa.", "subtitle": "Te acabamos de enviar un correo a %s,\npulsa en el enlace para confirmar tu cuenta.", - "tap_the_link_we_emailed_to_you_to_verify_your_account": "Tap the link we emailed to you to verify your account", + "tap_the_link_we_emailed_to_you_to_verify_your_account": "Toca el enlace que te enviamos por correo electrónico para verificar tu cuenta", "button": { "open_email_app": "Abrir Aplicación de Correo Electrónico", "resend": "Reenviar" @@ -347,8 +347,8 @@ "published": "¡Publicado!", "Publishing": "Publicación en curso...", "accessibility": { - "logo_label": "Logo Button", - "logo_hint": "Tap to scroll to top and tap again to previous location" + "logo_label": "Botón del logo", + "logo_hint": "Toca para desplazarte hacia arriba y toca de nuevo para la localización anterior" } } }, @@ -418,7 +418,7 @@ }, "profile": { "header": { - "follows_you": "Follows You" + "follows_you": "Te sigue" }, "dashboard": { "posts": "publicaciones", @@ -465,22 +465,22 @@ } }, "follower": { - "title": "follower", + "title": "seguidor", "footer": "No se muestran los seguidores de otros servidores." }, "following": { - "title": "following", + "title": "siguiendo", "footer": "No se muestran los seguidos de otros servidores." }, "familiarFollowers": { - "title": "Followers you familiar", - "followed_by_names": "Followed by %s" + "title": "Seguidores que conoces", + "followed_by_names": "Seguido por %s" }, "favorited_by": { - "title": "Favorited By" + "title": "Hecho favorito por" }, "reblogged_by": { - "title": "Reblogged By" + "title": "Reblogueado por" }, "search": { "title": "Buscar", @@ -520,10 +520,10 @@ "posts": "Publicaciones", "hashtags": "Etiquetas", "news": "Noticias", - "community": "Community", + "community": "Comunidad", "for_you": "Para Ti" }, - "intro": "These are the posts gaining traction in your corner of Mastodon." + "intro": "Estas son las publicaciones que están ganando tracción en tu rincón de Mastodon." }, "favorite": { "title": "Tus Favoritos" @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Mostrar Todo", "show_mentions": "Mostrar Menciones" + }, + "follow_request": { + "accept": "Aceptar", + "accepted": "Aceptado", + "reject": "rechazar", + "rejected": "Rechazado" } }, "thread": { @@ -620,46 +626,46 @@ "text_placeholder": "Escribe o pega comentarios adicionales", "reported": "REPORTADO", "step_one": { - "step_1_of_4": "Step 1 of 4", - "whats_wrong_with_this_post": "What's wrong with this post?", - "whats_wrong_with_this_account": "What's wrong with this account?", - "whats_wrong_with_this_username": "What's wrong with %s?", - "select_the_best_match": "Select the best match", - "i_dont_like_it": "I don’t like it", - "it_is_not_something_you_want_to_see": "It is not something you want to see", - "its_spam": "It’s spam", - "malicious_links_fake_engagement_or_repetetive_replies": "Malicious links, fake engagement, or repetetive replies", - "it_violates_server_rules": "It violates server rules", - "you_are_aware_that_it_breaks_specific_rules": "You are aware that it breaks specific rules", - "its_something_else": "It’s something else", - "the_issue_does_not_fit_into_other_categories": "The issue does not fit into other categories" + "step_1_of_4": "Paso 1 de 4", + "whats_wrong_with_this_post": "¿Qué hay de malo con esta publicación?", + "whats_wrong_with_this_account": "¿Qué hay de malo con esta cuenta?", + "whats_wrong_with_this_username": "¿Qué hay de malo con %s?", + "select_the_best_match": "Selecciona la mejor opción", + "i_dont_like_it": "No me gusta", + "it_is_not_something_you_want_to_see": "No es algo que quieras ver", + "its_spam": "Es spam", + "malicious_links_fake_engagement_or_repetetive_replies": "Enlaces maliciosos, compromisos falsos o respuestas repetitivas", + "it_violates_server_rules": "Viola las reglas del servidor", + "you_are_aware_that_it_breaks_specific_rules": "Eres consciente de que infringe las normas específicas", + "its_something_else": "Es algo más", + "the_issue_does_not_fit_into_other_categories": "El problema no encaja en otras categorías" }, "step_two": { - "step_2_of_4": "Step 2 of 4", - "which_rules_are_being_violated": "Which rules are being violated?", - "select_all_that_apply": "Select all that apply", - "i_just_don’t_like_it": "I just don’t like it" + "step_2_of_4": "Paso 2 de 4", + "which_rules_are_being_violated": "¿Qué normas se están violando?", + "select_all_that_apply": "Selecciona todos los que correspondan", + "i_just_don’t_like_it": "Solamente no me gusta" }, "step_three": { - "step_3_of_4": "Step 3 of 4", - "are_there_any_posts_that_back_up_this_report": "Are there any posts that back up this report?", - "select_all_that_apply": "Select all that apply" + "step_3_of_4": "Paso 3 de 4", + "are_there_any_posts_that_back_up_this_report": "¿Hay alguna publicación que respalde este informe?", + "select_all_that_apply": "Selecciona todos los que correspondan" }, "step_four": { - "step_4_of_4": "Step 4 of 4", - "is_there_anything_else_we_should_know": "Is there anything else we should know?" + "step_4_of_4": "Paso 4 de 4", + "is_there_anything_else_we_should_know": "¿Hay algo más que deberíamos saber?" }, "step_final": { - "dont_want_to_see_this": "Don’t want to see this?", - "when_you_see_something_you_dont_like_on_mastodon_you_can_remove_the_person_from_your_experience.": "When you see something you don’t like on Mastodon, you can remove the person from your experience.", - "unfollow": "Unfollow", - "unfollowed": "Unfollowed", - "unfollow_user": "Unfollow %s", - "mute_user": "Mute %s", - "you_wont_see_their_posts_or_reblogs_in_your_home_feed_they_wont_know_they_ve_been_muted": "You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted.", - "block_user": "Block %s", - "they_will_no_longer_be_able_to_follow_or_see_your_posts_but_they_can_see_if_theyve_been_blocked": "They will no longer be able to follow or see your posts, but they can see if they’ve been blocked.", - "while_we_review_this_you_can_take_action_against_user": "While we review this, you can take action against %s" + "dont_want_to_see_this": "¿No quieres ver esto?", + "when_you_see_something_you_dont_like_on_mastodon_you_can_remove_the_person_from_your_experience.": "Cuando veas algo que no te gusta en Mastodon, puedes quitar a la persona de tu experiencia.", + "unfollow": "Dejar de seguir", + "unfollowed": "Ha dejado de seguirte", + "unfollow_user": "Dejar de seguir a %s", + "mute_user": "Silenciar a %s", + "you_wont_see_their_posts_or_reblogs_in_your_home_feed_they_wont_know_they_ve_been_muted": "No verás sus publicaciones o reblogueos en tu línea temporal. No sabrán que han sido silenciados.", + "block_user": "Bloquear a %s", + "they_will_no_longer_be_able_to_follow_or_see_your_posts_but_they_can_see_if_theyve_been_blocked": "Ya no podrán ser capaces de seguirte o ver tus publicaciones, pero pueden ver si han sido bloqueados.", + "while_we_review_this_you_can_take_action_against_user": "Mientras revisamos esto, puedes tomar medidas contra %s" } }, "preview": { diff --git a/Localization/StringsConvertor/input/eu.lproj/app.json b/Localization/StringsConvertor/input/eu.lproj/app.json index 930aedabd..40b4bd623 100644 --- a/Localization/StringsConvertor/input/eu.lproj/app.json +++ b/Localization/StringsConvertor/input/eu.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Erakutsi guztia", "show_mentions": "Erakutsi aipamenak" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/fi.lproj/app.json b/Localization/StringsConvertor/input/fi.lproj/app.json index 9400a93f8..353ba989f 100644 --- a/Localization/StringsConvertor/input/fi.lproj/app.json +++ b/Localization/StringsConvertor/input/fi.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Näytä kaikki", "show_mentions": "Näytä maininnat" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/fr.lproj/app.json b/Localization/StringsConvertor/input/fr.lproj/app.json index dc148cbfa..dcb8750c4 100644 --- a/Localization/StringsConvertor/input/fr.lproj/app.json +++ b/Localization/StringsConvertor/input/fr.lproj/app.json @@ -418,7 +418,7 @@ }, "profile": { "header": { - "follows_you": "Follows You" + "follows_you": "Vous suit" }, "dashboard": { "posts": "publications", @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Tout Afficher", "show_mentions": "Afficher les mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/gd.lproj/app.json b/Localization/StringsConvertor/input/gd.lproj/app.json index 49fa60549..e2da7d6a9 100644 --- a/Localization/StringsConvertor/input/gd.lproj/app.json +++ b/Localization/StringsConvertor/input/gd.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Seall a h-uile càil", "show_mentions": "Seall na h-iomraidhean" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/gl.lproj/app.json b/Localization/StringsConvertor/input/gl.lproj/app.json index d6349cf01..3df2d70bc 100644 --- a/Localization/StringsConvertor/input/gl.lproj/app.json +++ b/Localization/StringsConvertor/input/gl.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Mostrar Todo", "show_mentions": "Mostrar mencións" + }, + "follow_request": { + "accept": "Aceptar", + "accepted": "Aceptada", + "reject": "rexeitar", + "rejected": "Rexeitada" } }, "thread": { diff --git a/Localization/StringsConvertor/input/hi.lproj/app.json b/Localization/StringsConvertor/input/hi.lproj/app.json index 69d03f003..23cfa481f 100644 --- a/Localization/StringsConvertor/input/hi.lproj/app.json +++ b/Localization/StringsConvertor/input/hi.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/id.lproj/app.json b/Localization/StringsConvertor/input/id.lproj/app.json index 675b53539..f56306e5d 100644 --- a/Localization/StringsConvertor/input/id.lproj/app.json +++ b/Localization/StringsConvertor/input/id.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Tampilkan Segalanya", "show_mentions": "Tampilkan Sebutan" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/it.lproj/app.json b/Localization/StringsConvertor/input/it.lproj/app.json index d61560c66..b5121b23f 100644 --- a/Localization/StringsConvertor/input/it.lproj/app.json +++ b/Localization/StringsConvertor/input/it.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Mostra Tutto", "show_mentions": "Mostra Menzioni" + }, + "follow_request": { + "accept": "Accetta", + "accepted": "Richiesta accettata", + "reject": "rifiuta", + "rejected": "Richiesta rifiutata" } }, "thread": { diff --git a/Localization/StringsConvertor/input/ja.lproj/Localizable.stringsdict b/Localization/StringsConvertor/input/ja.lproj/Localizable.stringsdict index 054b8cded..cbc999738 100644 --- a/Localization/StringsConvertor/input/ja.lproj/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/ja.lproj/Localizable.stringsdict @@ -92,7 +92,7 @@ NSStringFormatValueTypeKey ld other - %ld media + %ld件のメディア plural.count.post @@ -106,7 +106,7 @@ NSStringFormatValueTypeKey ld other - %ld posts + %ld件の投稿 plural.count.favorite @@ -148,7 +148,7 @@ NSStringFormatValueTypeKey ld other - %ld replies + %ld件の返信 plural.count.vote @@ -176,7 +176,7 @@ NSStringFormatValueTypeKey ld other - %ld voters + %ld人の投票 plural.people_talking @@ -316,7 +316,7 @@ NSStringFormatValueTypeKey ld other - %ld 年前 + %ld年前 date.month.ago.abbr diff --git a/Localization/StringsConvertor/input/ja.lproj/app.json b/Localization/StringsConvertor/input/ja.lproj/app.json index 4c7c9af89..039ef19fc 100644 --- a/Localization/StringsConvertor/input/ja.lproj/app.json +++ b/Localization/StringsConvertor/input/ja.lproj/app.json @@ -129,12 +129,12 @@ "show_post": "投稿を見る", "show_user_profile": "プロフィールを見る", "content_warning": "コンテンツ警告", - "sensitive_content": "Sensitive Content", + "sensitive_content": "閲覧注意", "media_content_warning": "どこかをタップして表示", "tap_to_reveal": "タップして表示", "poll": { "vote": "投票", - "closed": "クローズド" + "closed": "終了" }, "actions": { "reply": "返信", @@ -325,7 +325,7 @@ "tap_the_link_we_emailed_to_you_to_verify_your_account": "Tap the link we emailed to you to verify your account", "button": { "open_email_app": "メールアプリを開く", - "resend": "Resend" + "resend": "再送信" }, "dont_receive_email": { "title": "メールをチェックしてください", @@ -347,8 +347,8 @@ "published": "投稿しました!", "Publishing": "投稿中...", "accessibility": { - "logo_label": "Logo Button", - "logo_hint": "Tap to scroll to top and tap again to previous location" + "logo_label": "ロゴボタン", + "logo_hint": "タップすると一番上までスクロールし、もう一度タップすると元の場所に戻ります" } } }, @@ -418,7 +418,7 @@ }, "profile": { "header": { - "follows_you": "Follows You" + "follows_you": "フォローされています" }, "dashboard": { "posts": "投稿", @@ -441,20 +441,20 @@ }, "relationship_action_alert": { "confirm_mute_user": { - "title": "Mute Account", - "message": "Confirm to mute %s" + "title": "アカウントをミュート", + "message": "%sをミュートしますか?" }, "confirm_unmute_user": { "title": "ミュートを解除", "message": "%sをミュートしますか?" }, "confirm_block_user": { - "title": "Block Account", - "message": "Confirm to block %s" + "title": "アカウントをブロック", + "message": "%sをブロックしますか?" }, "confirm_unblock_user": { - "title": "Unblock Account", - "message": "Confirm to unblock %s" + "title": "アカウントのブロックを解除", + "message": "%sのブロックを解除しますか?" } }, "accessibility": { @@ -465,11 +465,11 @@ } }, "follower": { - "title": "follower", + "title": "フォロワー", "footer": "他のサーバーからのフォロワーは表示されません。" }, "following": { - "title": "following", + "title": "フォロー", "footer": "他のサーバーにいるフォローは表示されません。" }, "familiarFollowers": { @@ -534,16 +534,22 @@ "Mentions": "メンション" }, "notification_description": { - "followed_you": "さんにフォローされました", - "favorited_your_post": "さんがあなたの投稿をお気に入りに登録しました", - "reblogged_your_post": "さんがあなたの投稿をブーストしました", - "mentioned_you": "さんがあなたに返信しました", - "request_to_follow_you": "さんがあなたにフォローリクエストしました", - "poll_has_ended": "アンケートが終了しました" + "followed_you": "にフォローされました", + "favorited_your_post": "がお気に入りに登録", + "reblogged_your_post": "がブースト", + "mentioned_you": "にメンションされました", + "request_to_follow_you": "からのフォローリクエスト", + "poll_has_ended": "のアンケートが終了" }, "keyobard": { "show_everything": "すべて見る", "show_mentions": "メンションを見る" + }, + "follow_request": { + "accept": "承認", + "accepted": "承諾済み", + "reject": "拒否", + "rejected": "拒否済み" } }, "thread": { diff --git a/Localization/StringsConvertor/input/kab.lproj/app.json b/Localization/StringsConvertor/input/kab.lproj/app.json index 674cd220d..4ca5e0411 100644 --- a/Localization/StringsConvertor/input/kab.lproj/app.json +++ b/Localization/StringsConvertor/input/kab.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Sken yal taɣawsa", "show_mentions": "Sken tisedmirin" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/kmr.lproj/app.json b/Localization/StringsConvertor/input/kmr.lproj/app.json index 442c1e4fd..418c747f2 100644 --- a/Localization/StringsConvertor/input/kmr.lproj/app.json +++ b/Localization/StringsConvertor/input/kmr.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Her tiştî nîşan bide", "show_mentions": "Qalkirinan nîşan bike" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/ko.lproj/app.json b/Localization/StringsConvertor/input/ko.lproj/app.json index c2377420c..b66808919 100644 --- a/Localization/StringsConvertor/input/ko.lproj/app.json +++ b/Localization/StringsConvertor/input/ko.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "수락", + "accepted": "수락됨", + "reject": "거절", + "rejected": "거절됨" } }, "thread": { diff --git a/Localization/StringsConvertor/input/nl.lproj/app.json b/Localization/StringsConvertor/input/nl.lproj/app.json index 26ba573e1..91e651e04 100644 --- a/Localization/StringsConvertor/input/nl.lproj/app.json +++ b/Localization/StringsConvertor/input/nl.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Alles weergeven", "show_mentions": "Vermeldingen weergeven" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/pt-BR.lproj/app.json b/Localization/StringsConvertor/input/pt-BR.lproj/app.json index f4793d56e..872be790b 100644 --- a/Localization/StringsConvertor/input/pt-BR.lproj/app.json +++ b/Localization/StringsConvertor/input/pt-BR.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/pt.lproj/app.json b/Localization/StringsConvertor/input/pt.lproj/app.json index 93c3f9955..a965b23ae 100644 --- a/Localization/StringsConvertor/input/pt.lproj/app.json +++ b/Localization/StringsConvertor/input/pt.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/ro.lproj/app.json b/Localization/StringsConvertor/input/ro.lproj/app.json index 2c1f77d42..3a97d2222 100644 --- a/Localization/StringsConvertor/input/ro.lproj/app.json +++ b/Localization/StringsConvertor/input/ro.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/ru.lproj/app.json b/Localization/StringsConvertor/input/ru.lproj/app.json index 082bced1c..fa6377a2c 100644 --- a/Localization/StringsConvertor/input/ru.lproj/app.json +++ b/Localization/StringsConvertor/input/ru.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Показать все", "show_mentions": "Показать упоминания" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/sv.lproj/app.json b/Localization/StringsConvertor/input/sv.lproj/app.json index 224d466f3..537d6a270 100644 --- a/Localization/StringsConvertor/input/sv.lproj/app.json +++ b/Localization/StringsConvertor/input/sv.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Visa allt", "show_mentions": "Visa omnämningar" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/th.lproj/app.json b/Localization/StringsConvertor/input/th.lproj/app.json index 94b43845d..9c2a9f4f7 100644 --- a/Localization/StringsConvertor/input/th.lproj/app.json +++ b/Localization/StringsConvertor/input/th.lproj/app.json @@ -418,7 +418,7 @@ }, "profile": { "header": { - "follows_you": "Follows You" + "follows_you": "ติดตามคุณ" }, "dashboard": { "posts": "โพสต์", @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "แสดงทุกอย่าง", "show_mentions": "แสดงการกล่าวถึง" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/tr.lproj/app.json b/Localization/StringsConvertor/input/tr.lproj/app.json index 4e7b41942..27fb4e2b6 100644 --- a/Localization/StringsConvertor/input/tr.lproj/app.json +++ b/Localization/StringsConvertor/input/tr.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Her Şeyi Göster", "show_mentions": "Bahsetmeleri Göster" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Localization/StringsConvertor/input/vi.lproj/app.json b/Localization/StringsConvertor/input/vi.lproj/app.json index 60c13ca63..5d6df6910 100644 --- a/Localization/StringsConvertor/input/vi.lproj/app.json +++ b/Localization/StringsConvertor/input/vi.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Hiện mọi thứ", "show_mentions": "Hiện lượt nhắc" + }, + "follow_request": { + "accept": "Chấp nhận", + "accepted": "Đã chấp nhận", + "reject": "từ chối", + "rejected": "Đã từ chối" } }, "thread": { diff --git a/Localization/StringsConvertor/input/zh-Hans.lproj/app.json b/Localization/StringsConvertor/input/zh-Hans.lproj/app.json index c80c1ec83..90dbfc60e 100644 --- a/Localization/StringsConvertor/input/zh-Hans.lproj/app.json +++ b/Localization/StringsConvertor/input/zh-Hans.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "显示全部", "show_mentions": "显示提及" + }, + "follow_request": { + "accept": "接受", + "accepted": "已接受", + "reject": "拒绝", + "rejected": "已拒绝" } }, "thread": { diff --git a/Localization/StringsConvertor/input/zh-Hant.lproj/app.json b/Localization/StringsConvertor/input/zh-Hant.lproj/app.json index 8dd672020..b146a2942 100644 --- a/Localization/StringsConvertor/input/zh-Hant.lproj/app.json +++ b/Localization/StringsConvertor/input/zh-Hant.lproj/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "顯示全部", "show_mentions": "顯示提及" + }, + "follow_request": { + "accept": "接受", + "accepted": "已接受", + "reject": "拒絕", + "rejected": "已拒絕" } }, "thread": { diff --git a/Localization/app.json b/Localization/app.json index 93c3f9955..a965b23ae 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -544,6 +544,12 @@ "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" + }, + "follow_request": { + "accept": "Accept", + "accepted": "Accepted", + "reject": "reject", + "rejected": "Rejected" } }, "thread": { diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 4cf245769..c1fb3c70b 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4850,7 +4850,7 @@ CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4880,7 +4880,7 @@ CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4988,11 +4988,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 140; + DYLIB_CURRENT_VERSION = 144; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5019,11 +5019,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 140; + DYLIB_CURRENT_VERSION = 144; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5114,7 +5114,7 @@ CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5182,11 +5182,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 140; + DYLIB_CURRENT_VERSION = 144; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5211,7 +5211,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5234,7 +5234,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5258,7 +5258,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5282,7 +5282,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5306,7 +5306,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5330,7 +5330,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5354,7 +5354,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5441,7 +5441,7 @@ CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5508,11 +5508,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 140; + DYLIB_CURRENT_VERSION = 144; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -5536,7 +5536,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5559,7 +5559,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5583,7 +5583,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5607,7 +5607,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5630,7 +5630,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 140; + CURRENT_PROJECT_VERSION = 144; 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 02dc81778..49c20c414 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -19,7 +19,7 @@ Mastodon - Profile.xcscheme_^#shared#^_ orderHint - 1 + 3 Mastodon - RTL.xcscheme_^#shared#^_ @@ -114,7 +114,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 34 + 29 MastodonIntents.xcscheme_^#shared#^_ @@ -129,12 +129,12 @@ NotificationService.xcscheme_^#shared#^_ orderHint - 32 + 31 ShareActionExtension.xcscheme_^#shared#^_ orderHint - 33 + 30 SuppressBuildableAutocreation diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 4a4b43407..4491d383a 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -496,7 +496,7 @@ private extension SceneCoordinator { } let _viewController = SFSafariViewController(url: url) _viewController.preferredBarTintColor = ThemeService.shared.currentTheme.value.navigationBarBackgroundColor - _viewController.preferredControlTintColor = Asset.Colors.brandBlue.color + _viewController.preferredControlTintColor = Asset.Colors.brand.color viewController = _viewController case .alertController(let alertController): diff --git a/Mastodon/Extension/MastodonSDK/Mastodon+Entity+Notification+Type.swift b/Mastodon/Extension/MastodonSDK/Mastodon+Entity+Notification+Type.swift index 2c5a2e46e..2ffd5bcc3 100644 --- a/Mastodon/Extension/MastodonSDK/Mastodon+Entity+Notification+Type.swift +++ b/Mastodon/Extension/MastodonSDK/Mastodon+Entity+Notification+Type.swift @@ -17,7 +17,7 @@ extension Mastodon.Entity.Notification.NotificationType { var color: UIColor switch self { case .follow: - color = Asset.Colors.brandBlue.color + color = Asset.Colors.brand.color case .favourite: color = Asset.Colors.Notification.favourite.color case .reblog: @@ -25,9 +25,9 @@ extension Mastodon.Entity.Notification.NotificationType { case .mention: color = Asset.Colors.Notification.mention.color case .poll: - color = Asset.Colors.brandBlue.color + color = Asset.Colors.brand.color case .followRequest: - color = Asset.Colors.brandBlue.color + color = Asset.Colors.brand.color default: color = .clear } diff --git a/Mastodon/Extension/UITableView.swift b/Mastodon/Extension/UITableView.swift index 74bdd2ed4..9e2260e07 100644 --- a/Mastodon/Extension/UITableView.swift +++ b/Mastodon/Extension/UITableView.swift @@ -35,7 +35,7 @@ extension UITableView { let backgroundColor = cell.backgroundColor UIView.animate(withDuration: 0.3) { - cell.backgroundColor = Asset.Colors.brandBlue.color.withAlphaComponent(0.5) + cell.backgroundColor = Asset.Colors.brand.color.withAlphaComponent(0.5) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { UIView.animate(withDuration: 0.3) { cell.backgroundColor = backgroundColor diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index 1909cfab4..31b425322 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -2,6 +2,19 @@ + NSAppTransportSecurity + + NSExceptionDomains + + onion + + NSExceptionAllowsInsecureHTTPLoads + + NSIncludesSubdomains + + + + CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion @@ -17,7 +30,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleURLTypes @@ -30,7 +43,7 @@ CFBundleVersion - 140 + 144 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes @@ -46,19 +59,6 @@ LSRequiresIPhoneOS - NSAppTransportSecurity - - NSExceptionDomains - - onion - - NSExceptionAllowsInsecureHTTPLoads - - NSIncludesSubdomains - - - - NSUserActivityTypes SendPostIntent diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift index a1bf3136f..e9a0b02c0 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Block.swift @@ -14,7 +14,7 @@ extension DataSourceFacade { user: ManagedObjectRecord, authenticationBox: MastodonAuthenticationBox ) async throws { - let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() await selectionFeedbackGenerator.selectionChanged() _ = try await dependency.context.apiService.toggleBlock( diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Favorite.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Favorite.swift index a248ed42c..fba4f697b 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Favorite.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Favorite.swift @@ -15,7 +15,7 @@ extension DataSourceFacade { status: ManagedObjectRecord, authenticationBox: MastodonAuthenticationBox ) async throws { - let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() await selectionFeedbackGenerator.selectionChanged() _ = try await provider.context.apiService.favorite( diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Follow.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Follow.swift index b4f2362c3..535189368 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Follow.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Follow.swift @@ -7,6 +7,9 @@ import UIKit import CoreDataStack +import class CoreDataStack.Notification +import MastodonSDK +import MastodonLocalization extension DataSourceFacade { static func responseToUserFollowAction( @@ -14,7 +17,7 @@ extension DataSourceFacade { user: ManagedObjectRecord, authenticationBox: MastodonAuthenticationBox ) async throws { - let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() await selectionFeedbackGenerator.selectionChanged() _ = try await dependency.context.apiService.toggleFollow( @@ -23,3 +26,104 @@ extension DataSourceFacade { ) } // end func } + +extension DataSourceFacade { + static func responseToUserFollowRequestAction( + dependency: NeedsDependency, + notification: ManagedObjectRecord, + query: Mastodon.API.Account.FollowReqeustQuery, + authenticationBox: MastodonAuthenticationBox + ) async throws { + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() + await selectionFeedbackGenerator.selectionChanged() + + let managedObjectContext = dependency.context.managedObjectContext + let _userID: MastodonUser.ID? = try await managedObjectContext.perform { + guard let notification = notification.object(in: managedObjectContext) else { return nil } + return notification.account.id + } + + guard let userID = _userID else { + assertionFailure() + throw APIService.APIError.implicit(.badRequest) + } + + let state: MastodonFollowRequestState = try await managedObjectContext.perform { + guard let notification = notification.object(in: managedObjectContext) else { return .init(state: .none) } + return notification.followRequestState + } + + guard state.state == .none else { + return + } + + try? await managedObjectContext.performChanges { + guard let notification = notification.object(in: managedObjectContext) else { return } + switch query { + case .accept: + notification.transientFollowRequestState = .init(state: .isAccepting) + case .reject: + notification.transientFollowRequestState = .init(state: .isRejecting) + } + } + + do { + _ = try await dependency.context.apiService.followRequest( + userID: userID, + query: query, + authenticationBox: authenticationBox + ) + } catch { + try? await managedObjectContext.performChanges { + guard let notification = notification.object(in: managedObjectContext) else { return } + notification.transientFollowRequestState = .init(state: .none) + } + + if let error = error as? Mastodon.API.Error { + switch error.httpResponseStatus { + case .notFound: + let backgroundManagedObjectContext = dependency.context.backgroundManagedObjectContext + try await backgroundManagedObjectContext.performChanges { + guard let notification = notification.object(in: backgroundManagedObjectContext) else { return } + for feed in notification.feeds { + backgroundManagedObjectContext.delete(feed) + } + backgroundManagedObjectContext.delete(notification) + } + default: + let alertController = await UIAlertController(for: error, title: nil, preferredStyle: .alert) + let okAction = await UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default) + await alertController.addAction(okAction) + await dependency.coordinator.present( + scene: .alertController(alertController: alertController), + from: nil, + transition: .alertController(animated: true, completion: nil) + ) + } + } + + return + } + + try? await managedObjectContext.performChanges { + guard let notification = notification.object(in: managedObjectContext) else { return } + switch query { + case .accept: + notification.transientFollowRequestState = .init(state: .isAccept) + case .reject: + notification.transientFollowRequestState = .init(state: .isReject) + } + } + + let backgroundManagedObjectContext = dependency.context.backgroundManagedObjectContext + try? await backgroundManagedObjectContext.performChanges { + guard let notification = notification.object(in: backgroundManagedObjectContext) else { return } + switch query { + case .accept: + notification.followRequestState = .init(state: .isAccept) + case .reject: + notification.followRequestState = .init(state: .isReject) + } + } + } // end func +} diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Mute.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Mute.swift index 421d5046c..b5b2dec97 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Mute.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Mute.swift @@ -14,7 +14,7 @@ extension DataSourceFacade { user: ManagedObjectRecord, authenticationBox: MastodonAuthenticationBox ) async throws { - let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() await selectionFeedbackGenerator.selectionChanged() _ = try await dependency.context.apiService.toggleMute( diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Reblog.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Reblog.swift index 359b285d4..7eda84599 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Reblog.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Reblog.swift @@ -15,7 +15,7 @@ extension DataSourceFacade { status: ManagedObjectRecord, authenticationBox: MastodonAuthenticationBox ) async throws { - let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + let selectionFeedbackGenerator = await UISelectionFeedbackGenerator() await selectionFeedbackGenerator.selectionChanged() _ = try await provider.context.apiService.reblog( diff --git a/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift b/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift index ca7fdeb18..dab46bba8 100644 --- a/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift +++ b/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift @@ -87,6 +87,69 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider { } } +// MARK: - Follow Request +extension NotificationTableViewCellDelegate where Self: DataSourceProvider { + + func tableViewCell( + _ cell: UITableViewCell, + notificationView: NotificationView, + acceptFollowRequestButtonDidPressed button: UIButton + ) { + Task { + let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil) + guard let item = await item(from: source) else { + assertionFailure() + return + } + guard case let .notification(notification) = item else { + assertionFailure("only works for status data provider") + return + } + + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { + return + } + + try await DataSourceFacade.responseToUserFollowRequestAction( + dependency: self, + notification: notification, + query: .accept, + authenticationBox: authenticationBox + ) + } // end Task + } + + func tableViewCell( + _ cell: UITableViewCell, + notificationView: NotificationView, + rejectFollowRequestButtonDidPressed button: UIButton + ) { + Task { + let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil) + guard let item = await item(from: source) else { + assertionFailure() + return + } + guard case let .notification(notification) = item else { + assertionFailure("only works for status data provider") + return + } + + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { + return + } + + try await DataSourceFacade.responseToUserFollowRequestAction( + dependency: self, + notification: notification, + query: .reject, + authenticationBox: authenticationBox + ) + } // end Task + } + +} + // MARK: - Status Content extension NotificationTableViewCellDelegate where Self: DataSourceProvider { func tableViewCell( diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iOS-Marketing-1024@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iOS-Marketing-1024@1x.png new file mode 100644 index 000000000..a3d57d11a Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iOS-Marketing-1024@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-20@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-20@1x.png new file mode 100644 index 000000000..016311d94 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-20@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-20@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-20@2x.png new file mode 100644 index 000000000..effe1e25c Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-20@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-29@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-29@1x.png new file mode 100644 index 000000000..9845f4c49 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-29@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-29@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-29@2x.png new file mode 100644 index 000000000..6e46eab08 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-29@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-40@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-40@1x.png new file mode 100644 index 000000000..effe1e25c Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-40@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-40@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-40@2x.png new file mode 100644 index 000000000..59342c01e Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-40@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-76@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-76@1x.png new file mode 100644 index 000000000..f2c47274f Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-76@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-76@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-76@2x.png new file mode 100644 index 000000000..bc5f23049 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-76@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-83.5@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-83.5@2x.png new file mode 100644 index 000000000..906758b9b Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPad-83.5@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-20@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-20@2x.png new file mode 100644 index 000000000..effe1e25c Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-20@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-20@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-20@3x.png new file mode 100644 index 000000000..babaa4e0f Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-20@3x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@1x.png new file mode 100644 index 000000000..9845f4c49 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@2x.png new file mode 100644 index 000000000..6e46eab08 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@3x.png new file mode 100644 index 000000000..fc4f1a07b Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-29@3x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-40@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-40@2x.png new file mode 100644 index 000000000..59342c01e Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-40@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-40@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-40@3x.png new file mode 100644 index 000000000..45cdb81c1 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-40@3x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-57@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-57@1x.png new file mode 100644 index 000000000..f03bc5e46 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-57@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-57@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-57@2x.png new file mode 100644 index 000000000..f3934711d Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-57@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-60@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-60@2x.png new file mode 100644 index 000000000..45cdb81c1 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-60@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-60@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-60@3x.png new file mode 100644 index 000000000..07d0c7869 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~iPhone-60@3x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-128@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-128@1x.png new file mode 100644 index 000000000..c7c5a678d Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-128@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-128@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-128@2x.png new file mode 100644 index 000000000..a6963f84c Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-128@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-16@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-16@1x.png new file mode 100644 index 000000000..53c671512 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-16@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-16@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-16@2x.png new file mode 100644 index 000000000..6bc4424f1 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-16@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-256@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-256@1x.png new file mode 100644 index 000000000..a6963f84c Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-256@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-256@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-256@2x.png new file mode 100644 index 000000000..908880d8d Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-256@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-32@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-32@1x.png new file mode 100644 index 000000000..6bc4424f1 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-32@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-32@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-32@2x.png new file mode 100644 index 000000000..1f37871e3 Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-32@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-512@1x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-512@1x.png new file mode 100644 index 000000000..908880d8d Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-512@1x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-512@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-512@2x.png new file mode 100644 index 000000000..a3d57d11a Binary files /dev/null and b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon~macOS-512@2x.png differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json index a0a28b621..46683a282 100644 --- a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,112 +1,190 @@ { "images" : [ { - "filename" : "icon_20pt@2x.png", + "filename" : "AppIcon~iPhone-20@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "20x20" }, { - "filename" : "icon_20pt@3x.png", + "filename" : "AppIcon~iPhone-20@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "20x20" }, { - "filename" : "icon_29pt@2x.png", + "filename" : "AppIcon~iPhone-29@1x.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "AppIcon~iPhone-29@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "29x29" }, { - "filename" : "icon_29pt@3x.png", + "filename" : "AppIcon~iPhone-29@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "29x29" }, { - "filename" : "icon_40pt@2x.png", + "filename" : "AppIcon~iPhone-40@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "40x40" }, { - "filename" : "icon_40pt@3x.png", + "filename" : "AppIcon~iPhone-40@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "40x40" }, { - "filename" : "icon_60pt@2x.png", + "filename" : "AppIcon~iPhone-57@1x.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "57x57" + }, + { + "filename" : "AppIcon~iPhone-57@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "57x57" + }, + { + "filename" : "AppIcon~iPhone-60@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "60x60" }, { - "filename" : "icon_60pt@3x.png", + "filename" : "AppIcon~iPhone-60@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "60x60" }, { - "filename" : "icon_20pt.png", + "filename" : "AppIcon~iPad-20@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "20x20" }, { - "filename" : "icon_20pt@2x-1.png", + "filename" : "AppIcon~iPad-20@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "20x20" }, { - "filename" : "icon_29pt.png", + "filename" : "AppIcon~iPad-29@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "29x29" }, { - "filename" : "icon_29pt@2x-1.png", + "filename" : "AppIcon~iPad-29@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "29x29" }, { - "filename" : "icon_40pt.png", + "filename" : "AppIcon~iPad-40@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "40x40" }, { - "filename" : "icon_40pt@2x-1.png", + "filename" : "AppIcon~iPad-40@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "40x40" }, { - "filename" : "icon_76pt.png", + "filename" : "AppIcon~iPad-76@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "76x76" }, { - "filename" : "icon_76pt@2x.png", + "filename" : "AppIcon~iPad-76@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "76x76" }, { - "filename" : "icon_83.5@2x.png", + "filename" : "AppIcon~iPad-83.5@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "83.5x83.5" }, { - "filename" : "iTunesArtwork@2x.png", + "filename" : "AppIcon~iOS-Marketing-1024@1x.png", "idiom" : "ios-marketing", "scale" : "1x", "size" : "1024x1024" + }, + { + "filename" : "AppIcon~macOS-16@1x.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "filename" : "AppIcon~macOS-16@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "filename" : "AppIcon~macOS-32@1x.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "filename" : "AppIcon~macOS-32@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "filename" : "AppIcon~macOS-128@1x.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "filename" : "AppIcon~macOS-128@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "filename" : "AppIcon~macOS-256@1x.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "filename" : "AppIcon~macOS-256@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "filename" : "AppIcon~macOS-512@1x.png", + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "filename" : "AppIcon~macOS-512@2x.png", + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" } ], "info" : { diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png deleted file mode 100644 index cc435d6f6..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt.png deleted file mode 100644 index ae8e49ce1..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png deleted file mode 100644 index 965ec2014..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x-1.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png deleted file mode 100644 index 965ec2014..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@2x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png deleted file mode 100644 index 3d0267ca3..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_20pt@3x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt.png deleted file mode 100644 index 7e77b9bed..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png deleted file mode 100644 index ccb3c08e7..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x-1.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png deleted file mode 100644 index ccb3c08e7..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@2x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png deleted file mode 100644 index d288ff81f..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_29pt@3x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt.png deleted file mode 100644 index 965ec2014..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png deleted file mode 100644 index 35726ff68..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x-1.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png deleted file mode 100644 index 35726ff68..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@2x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png deleted file mode 100644 index adf3d119d..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_40pt@3x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png deleted file mode 100644 index adf3d119d..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_60pt@2x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png deleted file mode 100644 index 588f66037..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_60pt@3x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_76pt.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_76pt.png deleted file mode 100644 index 1b5a86220..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_76pt.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png deleted file mode 100644 index c6000830a..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_76pt@2x.png and /dev/null differ diff --git a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png b/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png deleted file mode 100644 index d5705366e..000000000 Binary files a/Mastodon/Resources/Assets.xcassets/AppIcon.appiconset/icon_83.5@2x.png and /dev/null differ diff --git a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollExpiresOptionCollectionViewCell.swift b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollExpiresOptionCollectionViewCell.swift index 7d976bfdf..8a00fccde 100644 --- a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollExpiresOptionCollectionViewCell.swift +++ b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollExpiresOptionCollectionViewCell.swift @@ -25,7 +25,7 @@ final class ComposeStatusPollExpiresOptionCollectionViewCell: UICollectionViewCe button.titleLabel?.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 12)) button.expandEdgeInsets = UIEdgeInsets(top: 0, left: -10, bottom: -20, right: -20) button.setTitle(L10n.Scene.Compose.Poll.durationTime(L10n.Scene.Compose.Poll.thirtyMinutes), for: .normal) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) + button.setTitleColor(Asset.Colors.brand.color, for: .normal) return button }() diff --git a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift index e2702e7c6..336d109c9 100644 --- a/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift +++ b/Mastodon/Scene/Compose/CollectionViewCell/ComposeStatusPollOptionAppendEntryCollectionViewCell.swift @@ -32,7 +32,7 @@ final class ComposeStatusPollOptionAppendEntryCollectionViewCell: UICollectionVi override var isHighlighted: Bool { didSet { pollOptionView.roundedBackgroundView.backgroundColor = isHighlighted ? ThemeService.shared.currentTheme.value.tertiarySystemGroupedBackgroundColor.withAlphaComponent(0.6) : ThemeService.shared.currentTheme.value.tertiarySystemGroupedBackgroundColor - pollOptionView.plusCircleImageView.tintColor = isHighlighted ? Asset.Colors.brandBlue.color.withAlphaComponent(0.5) : Asset.Colors.brandBlue.color + pollOptionView.plusCircleImageView.tintColor = isHighlighted ? Asset.Colors.brand.color.withAlphaComponent(0.5) : Asset.Colors.brand.color } } diff --git a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift index 4c3d37169..814d79c0e 100644 --- a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift +++ b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift @@ -60,7 +60,7 @@ final class ComposeStatusContentTableViewCell: UITableViewCell { ] metaText.linkAttributes = [ .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)), - .foregroundColor: Asset.Colors.brandBlue.color, + .foregroundColor: Asset.Colors.brand.color, ] return metaText }() diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 871d47c28..24b96f265 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -339,7 +339,7 @@ extension HomeTimelineViewController { let button = HighlightDimmableButton() button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)) button.setTitle(L10n.Common.Controls.Actions.manuallySearch, for: .normal) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) + button.setTitleColor(Asset.Colors.brand.color, for: .normal) button.addTarget(self, action: #selector(HomeTimelineViewController.manuallySearchButtonPressed(_:)), for: .touchUpInside) return button }() diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift index 756a4b608..35f44683a 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift @@ -180,136 +180,3 @@ extension HomeTimelineViewModel { } } - - - - -//// MARK: - NSFetchedResultsControllerDelegate -//extension HomeTimelineViewModel: NSFetchedResultsControllerDelegate { -// -// func controllerWillChangeContent(_ controller: NSFetchedResultsController) { -// os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) -// } -// -// func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) { -// os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) -// -// guard let tableView = self.tableView else { return } -// guard let navigationBar = self.contentOffsetAdjustableTimelineViewControllerDelegate?.navigationBar() else { return } -// -// guard let diffableDataSource = self.diffableDataSource else { return } -// let oldSnapshot = diffableDataSource.snapshot() -// -// let predicate = fetchedResultsController.fetchRequest.predicate -// let parentManagedObjectContext = fetchedResultsController.managedObjectContext -// let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) -// managedObjectContext.parent = parentManagedObjectContext -// -// managedObjectContext.perform { -// var shouldAddBottomLoader = false -// -// let timelineIndexes: [HomeTimelineIndex] = { -// let request = HomeTimelineIndex.sortedFetchRequest -// request.returnsObjectsAsFaults = false -// request.predicate = predicate -// do { -// return try managedObjectContext.fetch(request) -// } catch { -// assertionFailure(error.localizedDescription) -// return [] -// } -// }() -// -// // that's will be the most fastest fetch because of upstream just update and no modify needs consider -// -// var oldSnapshotAttributeDict: [NSManagedObjectID : Item.StatusAttribute] = [:] -// -// for item in oldSnapshot.itemIdentifiers { -// guard case let .homeTimelineIndex(objectID, attribute) = item else { continue } -// oldSnapshotAttributeDict[objectID] = attribute -// } -// -// var newTimelineItems: [Item] = [] -// -// for (i, timelineIndex) in timelineIndexes.enumerated() { -// let attribute = oldSnapshotAttributeDict[timelineIndex.objectID] ?? Item.StatusAttribute() -// attribute.isSeparatorLineHidden = false -// -// // append new item into snapshot -// newTimelineItems.append(.homeTimelineIndex(objectID: timelineIndex.objectID, attribute: attribute)) -// -// let isLast = i == timelineIndexes.count - 1 -// switch (isLast, timelineIndex.hasMore) { -// case (false, true): -// newTimelineItems.append(.homeMiddleLoader(upperTimelineIndexAnchorObjectID: timelineIndex.objectID)) -// attribute.isSeparatorLineHidden = true -// case (true, true): -// shouldAddBottomLoader = true -// default: -// break -// } -// } // end for -// -// var newSnapshot = NSDiffableDataSourceSnapshot() -// newSnapshot.appendSections([.main]) -// newSnapshot.appendItems(newTimelineItems, toSection: .main) -// -// let endSnapshot = CACurrentMediaTime() -// -// DispatchQueue.main.async { -// if shouldAddBottomLoader, !(self.loadLatestStateMachine.currentState is LoadOldestState.NoMore) { -// newSnapshot.appendItems([.bottomLoader], toSection: .main) -// } -// -// guard let difference = self.calculateReloadSnapshotDifference(navigationBar: navigationBar, tableView: tableView, oldSnapshot: oldSnapshot, newSnapshot: newSnapshot) else { -// diffableDataSource.apply(newSnapshot) -// self.isFetchingLatestTimeline.value = false -// return -// } -// -// diffableDataSource.reloadData(snapshot: newSnapshot) { -// tableView.scrollToRow(at: difference.targetIndexPath, at: .top, animated: false) -// tableView.contentOffset.y = tableView.contentOffset.y - difference.offset -// self.isFetchingLatestTimeline.value = false -// } -// -// let end = CACurrentMediaTime() -// os_log("%{public}s[%{public}ld], %{public}s: calculate home timeline layout cost %.2fs", ((#file as NSString).lastPathComponent), #line, #function, end - endSnapshot) -// } -// } // end perform -// } -// -// private struct Difference { -// let item: T -// let sourceIndexPath: IndexPath -// let targetIndexPath: IndexPath -// let offset: CGFloat -// } -// -// private func calculateReloadSnapshotDifference( -// navigationBar: UINavigationBar, -// tableView: UITableView, -// oldSnapshot: NSDiffableDataSourceSnapshot, -// newSnapshot: NSDiffableDataSourceSnapshot -// ) -> Difference? { -// guard oldSnapshot.numberOfItems != 0 else { return nil } -// -// // old snapshot not empty. set source index path to first item if not match -// let sourceIndexPath = UIViewController.topVisibleTableViewCellIndexPath(in: tableView, navigationBar: navigationBar) ?? IndexPath(row: 0, section: 0) -// -// guard sourceIndexPath.row < oldSnapshot.itemIdentifiers(inSection: .main).count else { return nil } -// -// let timelineItem = oldSnapshot.itemIdentifiers(inSection: .main)[sourceIndexPath.row] -// guard let itemIndex = newSnapshot.itemIdentifiers(inSection: .main).firstIndex(of: timelineItem) else { return nil } -// let targetIndexPath = IndexPath(row: itemIndex, section: 0) -// -// let offset = UIViewController.tableViewCellOriginOffsetToWindowTop(in: tableView, at: sourceIndexPath, navigationBar: navigationBar) -// return Difference( -// item: timelineItem, -// sourceIndexPath: sourceIndexPath, -// targetIndexPath: targetIndexPath, -// offset: offset -// ) -// } -// -//} diff --git a/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift b/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift index 016884f72..400b4ee98 100644 --- a/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift +++ b/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift @@ -114,7 +114,7 @@ extension HomeTimelineNavigationBarTitleView { configureButton( title: L10n.Scene.HomeTimeline.NavigationBarState.newPosts, textColor: .white, - backgroundColor: Asset.Colors.brandBlue.color + backgroundColor: Asset.Colors.brand.color ) button.isHidden = false button.accessibilityLabel = L10n.Scene.HomeTimeline.NavigationBarState.newPosts diff --git a/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift b/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift index d13ce7195..7a603d5f0 100644 --- a/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift +++ b/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift @@ -25,6 +25,8 @@ protocol NotificationTableViewCellDelegate: AnyObject, AutoGenerateProtocolDeleg // sourcery:inline:NotificationTableViewCellDelegate.AutoGenerateProtocolDelegate func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, authorAvatarButtonDidPressed button: AvatarButton) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action) + func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, acceptFollowRequestButtonDidPressed button: UIButton) + func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, rejectFollowRequestButtonDidPressed button: UIButton) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) @@ -49,6 +51,14 @@ extension NotificationViewDelegate where Self: NotificationViewContainerTableVie delegate?.tableViewCell(self, notificationView: notificationView, menuButton: button, didSelectAction: action) } + func notificationView(_ notificationView: NotificationView, acceptFollowRequestButtonDidPressed button: UIButton) { + delegate?.tableViewCell(self, notificationView: notificationView, acceptFollowRequestButtonDidPressed: button) + } + + func notificationView(_ notificationView: NotificationView, rejectFollowRequestButtonDidPressed button: UIButton) { + delegate?.tableViewCell(self, notificationView: notificationView, rejectFollowRequestButtonDidPressed: button) + } + func notificationView(_ notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) { delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, metaText: metaText, didSelectMeta: meta) } diff --git a/Mastodon/Scene/Notification/NotificationViewModel.swift b/Mastodon/Scene/Notification/NotificationViewModel.swift index 3d4fa6042..60967c436 100644 --- a/Mastodon/Scene/Notification/NotificationViewModel.swift +++ b/Mastodon/Scene/Notification/NotificationViewModel.swift @@ -43,42 +43,6 @@ extension NotificationTimelineViewModel.Scope { } } -// func acceptFollowRequest(notification: MastodonNotification) { -// guard let activeMastodonAuthenticationBox = self.activeMastodonAuthenticationBox.value else { return } -// context.apiService.acceptFollowRequest(mastodonUserID: notification.account.id, mastodonAuthenticationBox: activeMastodonAuthenticationBox) -// .sink { [weak self] completion in -// switch completion { -// case .failure(let error): -// os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: accept FollowRequest fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) -// case .finished: -// break -//// self?.loadLatestStateMachine.enter(NotificationViewModel.LoadLatestState.Loading.self) -// } -// } receiveValue: { _ in -// -// } -// .store(in: &disposeBag) -// } -// -// func rejectFollowRequest(notification: MastodonNotification) { -// guard let activeMastodonAuthenticationBox = self.activeMastodonAuthenticationBox.value else { return } -// context.apiService.rejectFollowRequest(mastodonUserID: notification.account.id, mastodonAuthenticationBox: activeMastodonAuthenticationBox) -// .sink { [weak self] completion in -// switch completion { -// case .failure(let error): -// os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: reject FollowRequest fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) -// case .finished: -// break -//// self?.loadLatestStateMachine.enter(NotificationViewModel.LoadLatestState.Loading.self) -// } -// } receiveValue: { _ in -// -// } -// .store(in: &disposeBag) -// } -//} - - // MARK: - PageboyViewControllerDataSource extension NotificationViewModel: PageboyViewControllerDataSource { diff --git a/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift b/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift index 822085863..784559480 100644 --- a/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift +++ b/Mastodon/Scene/Onboarding/PickServer/View/PickServerCategoryView.swift @@ -65,7 +65,7 @@ extension PickServerCategoryView { highlightedIndicatorView.translatesAutoresizingMaskIntoConstraints = false container.addArrangedSubview(highlightedIndicatorView) NSLayoutConstraint.activate([ - highlightedIndicatorView.heightAnchor.constraint(equalToConstant: UIView.separatorLineHeight(of: self) * 3).priority(.required - 1), + highlightedIndicatorView.heightAnchor.constraint(equalToConstant: 3).priority(.required - 1), ]) titleLabel.setContentHuggingPriority(.required - 1, for: .vertical) } diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift index d99b90bc4..ac71c0a5f 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift @@ -211,7 +211,7 @@ final class ProfileHeaderView: UIView { ] metaText.linkAttributes = [ .font: UIFont.preferredFont(forTextStyle: .body), - .foregroundColor: Asset.Colors.brandBlue.color, + .foregroundColor: Asset.Colors.brand.color, ] return metaText }() diff --git a/Mastodon/Scene/Profile/ProfileViewModel.swift b/Mastodon/Scene/Profile/ProfileViewModel.swift index 79bfe8986..9d64df6ee 100644 --- a/Mastodon/Scene/Profile/ProfileViewModel.swift +++ b/Mastodon/Scene/Profile/ProfileViewModel.swift @@ -68,7 +68,7 @@ class ProfileViewModel: NSObject { self.repliesUserTimelineViewModel = UserTimelineViewModel( context: context, title: L10n.Scene.Profile.SegmentedControl.postsAndReplies, - queryFilter: .init(excludeReplies: true) + queryFilter: .init(excludeReplies: false) ) self.mediaUserTimelineViewModel = UserTimelineViewModel( context: context, diff --git a/Mastodon/Scene/Root/Sidebar/View/SidebarAddAccountCollectionViewCell.swift b/Mastodon/Scene/Root/Sidebar/View/SidebarAddAccountCollectionViewCell.swift index da3793a9c..cd8ae1d57 100644 --- a/Mastodon/Scene/Root/Sidebar/View/SidebarAddAccountCollectionViewCell.swift +++ b/Mastodon/Scene/Root/Sidebar/View/SidebarAddAccountCollectionViewCell.swift @@ -34,7 +34,7 @@ extension SidebarAddAccountCollectionViewCell { // Customize the background color to use the tint color when the cell is highlighted or selected. if state.isSelected || state.isHighlighted { - newBackgroundConfiguration.backgroundColor = Asset.Colors.brandBlue.color + newBackgroundConfiguration.backgroundColor = Asset.Colors.brand.color } if state.isHighlighted { newBackgroundConfiguration.backgroundColorTransformer = .init { $0.withAlphaComponent(0.8) } diff --git a/Mastodon/Scene/Search/Search/View/SearchRecommendCollectionHeader.swift b/Mastodon/Scene/Search/Search/View/SearchRecommendCollectionHeader.swift index 0b7495cc8..19d2e9d4b 100644 --- a/Mastodon/Scene/Search/Search/View/SearchRecommendCollectionHeader.swift +++ b/Mastodon/Scene/Search/Search/View/SearchRecommendCollectionHeader.swift @@ -31,7 +31,7 @@ class SearchRecommendCollectionHeader: UIView { let seeAllButton: HighlightDimmableButton = { let button = HighlightDimmableButton(type: .custom) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) + button.setTitleColor(Asset.Colors.brand.color, for: .normal) button.setTitle(L10n.Scene.Search.Recommend.buttonText, for: .normal) button.titleLabel?.adjustsFontSizeToFitWidth = true button.titleLabel?.minimumScaleFactor = 0.8 diff --git a/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift b/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift index ecc1c0c02..701dc4fa6 100644 --- a/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift +++ b/Mastodon/Scene/Search/SearchDetail/SearchDetailViewController.swift @@ -306,7 +306,7 @@ extension SearchDetailViewController { private func setupBackgroundColor(theme: Theme) { navigationBarBackgroundView.backgroundColor = theme.navigationBarBackgroundColor - navigationBar.tintColor = Asset.Colors.brandBlue.color + navigationBar.tintColor = Asset.Colors.brand.color } } diff --git a/Mastodon/Scene/Search/SearchDetail/SearchHistory/View/SearchHistoryTableHeaderView.swift b/Mastodon/Scene/Search/SearchDetail/SearchHistory/View/SearchHistoryTableHeaderView.swift index fc41bdf27..5de09f802 100644 --- a/Mastodon/Scene/Search/SearchDetail/SearchHistory/View/SearchHistoryTableHeaderView.swift +++ b/Mastodon/Scene/Search/SearchDetail/SearchHistory/View/SearchHistoryTableHeaderView.swift @@ -34,7 +34,7 @@ final class SearchHistoryTableHeaderView: UIView { let clearSearchHistoryButton: HighlightDimmableButton = { let button = HighlightDimmableButton(type: .custom) button.expandEdgeInsets = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) + button.setTitleColor(Asset.Colors.brand.color, for: .normal) button.setTitle(L10n.Scene.Search.Searching.clear, for: .normal) return button }() diff --git a/Mastodon/Scene/Share/View/Content/NavigationBarProgressView.swift b/Mastodon/Scene/Share/View/Content/NavigationBarProgressView.swift index efa8b53a5..e2b7a4d01 100644 --- a/Mastodon/Scene/Share/View/Content/NavigationBarProgressView.swift +++ b/Mastodon/Scene/Share/View/Content/NavigationBarProgressView.swift @@ -15,7 +15,7 @@ class NavigationBarProgressView: UIView { let sliderView: UIView = { let view = UIView() - view.backgroundColor = Asset.Colors.brandBlue.color + view.backgroundColor = Asset.Colors.brand.color view.translatesAutoresizingMaskIntoConstraints = false return view }() diff --git a/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift b/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift index 052dc44c2..45652321f 100644 --- a/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift +++ b/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift @@ -29,6 +29,8 @@ extension NotificationView { extension NotificationView { public func configure(notification: Notification) { + viewModel.objects.insert(notification) + configureAuthor(notification: notification) guard let type = MastodonNotificationType(rawValue: notification.typeRaw) else { @@ -36,23 +38,26 @@ extension NotificationView { return } - if let status = notification.status { - switch type { - case .follow, .followRequest: - setAuthorContainerBottomPaddingViewDisplay() - case .mention, .status: + switch type { + case .follow: + setAuthorContainerBottomPaddingViewDisplay() + case .followRequest: + setFollowRequestAdaptiveMarginContainerViewDisplay() + case .mention, .status: + if let status = notification.status { statusView.configure(status: status) setStatusViewDisplay() - case .reblog, .favourite, .poll: + } + case .reblog, .favourite, .poll: + if let status = notification.status { quoteStatusView.configure(status: status) setQuoteStatusViewDisplay() - case ._other: - setAuthorContainerBottomPaddingViewDisplay() - assertionFailure() } - } else { + case ._other: setAuthorContainerBottomPaddingViewDisplay() + assertionFailure() } + } } @@ -195,5 +200,12 @@ extension NotificationView { } .assign(to: \.isMyself, on: viewModel) .store(in: &disposeBag) + // follow request state + notification.publisher(for: \.followRequestState) + .assign(to: \.followRequestState, on: viewModel) + .store(in: &disposeBag) + notification.publisher(for: \.transientFollowRequestState) + .assign(to: \.transientFollowRequestState, on: viewModel) + .store(in: &disposeBag) } } diff --git a/Mastodon/Service/APIService/APIService+FollowRequest.swift b/Mastodon/Service/APIService/APIService+FollowRequest.swift index b2029f3db..5c91d282c 100644 --- a/Mastodon/Service/APIService/APIService+FollowRequest.swift +++ b/Mastodon/Service/APIService/APIService+FollowRequest.swift @@ -15,91 +15,42 @@ import CommonOSLog import MastodonSDK extension APIService { -// func acceptFollowRequest( -// mastodonUserID: MastodonUser.ID, -// mastodonAuthenticationBox: MastodonAuthenticationBox -// ) -> AnyPublisher, Error> { -// let domain = mastodonAuthenticationBox.domain -// let authorization = mastodonAuthenticationBox.userAuthorization -// let requestMastodonUserID = mastodonAuthenticationBox.userID -// -// return Mastodon.API.Account.acceptFollowRequest( -// session: session, -// domain: domain, -// userID: mastodonUserID, -// 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 } -// -// let lookUpMastodonUserRequest = MastodonUser.sortedFetchRequest -// lookUpMastodonUserRequest.predicate = MastodonUser.predicate(domain: domain, id: mastodonUserID) -// lookUpMastodonUserRequest.fetchLimit = 1 -// let lookUpMastodonuser = managedObjectContext.safeFetch(lookUpMastodonUserRequest).first -// -// if let lookUpMastodonuser = lookUpMastodonuser { -// let entity = response.value -// APIService.CoreData.update(user: lookUpMastodonuser, entity: entity, requestMastodonUser: requestMastodonUser, domain: domain, networkDate: response.networkDate) -// } -// } -// .tryMap { result -> Mastodon.Response.Content in -// switch result { -// case .success: -// return response -// case .failure(let error): -// throw error -// } -// } -// .eraseToAnyPublisher() -// } -// .eraseToAnyPublisher() -// } -// func rejectFollowRequest( -// mastodonUserID: MastodonUser.ID, -// mastodonAuthenticationBox: MastodonAuthenticationBox -// ) -> AnyPublisher, Error> { -// let domain = mastodonAuthenticationBox.domain -// let authorization = mastodonAuthenticationBox.userAuthorization -// let requestMastodonUserID = mastodonAuthenticationBox.userID -// -// return Mastodon.API.Account.rejectFollowRequest( -// session: session, -// domain: domain, -// userID: mastodonUserID, -// 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 } -// -// let lookUpMastodonUserRequest = MastodonUser.sortedFetchRequest -// lookUpMastodonUserRequest.predicate = MastodonUser.predicate(domain: domain, id: mastodonUserID) -// lookUpMastodonUserRequest.fetchLimit = 1 -// let lookUpMastodonuser = managedObjectContext.safeFetch(lookUpMastodonUserRequest).first -// -// if let lookUpMastodonuser = lookUpMastodonuser { -// let entity = response.value -// APIService.CoreData.update(user: lookUpMastodonuser, entity: entity, requestMastodonUser: requestMastodonUser, domain: domain, networkDate: response.networkDate) -// } -// } -// .tryMap { result -> Mastodon.Response.Content in -// switch result { -// case .success: -// return response -// case .failure(let error): -// throw error -// } -// } -// .eraseToAnyPublisher() -// } -// .eraseToAnyPublisher() -// } + func followRequest( + userID: Mastodon.Entity.Account.ID, + query: Mastodon.API.Account.FollowReqeustQuery, + authenticationBox: MastodonAuthenticationBox + ) async throws -> Mastodon.Response.Content { + let response = try await Mastodon.API.Account.followRequest( + session: session, + domain: authenticationBox.domain, + userID: userID, + query: query, + authorization: authenticationBox.userAuthorization + ).singleOutput() + + let managedObjectContext = self.backgroundManagedObjectContext + try await managedObjectContext.performChanges { + let request = MastodonUser.sortedFetchRequest + request.predicate = MastodonUser.predicate( + domain: authenticationBox.domain, + id: authenticationBox.userID + ) + request.fetchLimit = 1 + guard let user = managedObjectContext.safeFetch(request).first else { return } + guard let me = authenticationBox.authenticationRecord.object(in: managedObjectContext)?.user else { return } + + Persistence.MastodonUser.update( + mastodonUser: user, + context: Persistence.MastodonUser.RelationshipContext( + entity: response.value, + me: me, + networkDate: response.networkDate + ) + ) + } + + return response + } + } diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index cf6041f3c..05a3cc313 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleVersion - 140 + 144 NSExtension NSExtensionAttributes diff --git a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents index 16a1c7c84..10c420eee 100644 --- a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents +++ b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -113,7 +113,9 @@ + + @@ -255,7 +257,7 @@ - + diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Notification.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Notification.swift index 85019b0dc..7eec86842 100644 --- a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Notification.swift +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Notification.swift @@ -36,6 +36,58 @@ public final class Notification: NSManagedObject { } +extension Notification { + // sourcery: autoUpdatableObject + @objc public var followRequestState: MastodonFollowRequestState { + get { + let keyPath = #keyPath(Notification.followRequestState) + willAccessValue(forKey: keyPath) + let _data = primitiveValue(forKey: keyPath) as? Data + didAccessValue(forKey: keyPath) + do { + guard let data = _data, !data.isEmpty else { return .init(state: .none) } + let state = try JSONDecoder().decode(MastodonFollowRequestState.self, from: data) + return state + } catch { + assertionFailure(error.localizedDescription) + return .init(state: .none) + } + } + set { + let keyPath = #keyPath(Notification.followRequestState) + let data = try? JSONEncoder().encode(newValue) + willChangeValue(forKey: keyPath) + setPrimitiveValue(data, forKey: keyPath) + didChangeValue(forKey: keyPath) + } + } + + // sourcery: autoUpdatableObject + @objc public var transientFollowRequestState: MastodonFollowRequestState { + get { + let keyPath = #keyPath(Notification.transientFollowRequestState) + willAccessValue(forKey: keyPath) + let _data = primitiveValue(forKey: keyPath) as? Data + didAccessValue(forKey: keyPath) + do { + guard let data = _data else { return .init(state: .none) } + let state = try JSONDecoder().decode(MastodonFollowRequestState.self, from: data) + return state + } catch { + assertionFailure(error.localizedDescription) + return .init(state: .none) + } + } + set { + let keyPath = #keyPath(Notification.transientFollowRequestState) + let data = try? JSONEncoder().encode(newValue) + willChangeValue(forKey: keyPath) + setPrimitiveValue(data, forKey: keyPath) + didChangeValue(forKey: keyPath) + } + } +} + extension Notification: FeedIndexable { } extension Notification { @@ -197,6 +249,16 @@ extension Notification: AutoUpdatableObject { self.updatedAt = updatedAt } } + public func update(followRequestState: MastodonFollowRequestState) { + if self.followRequestState != followRequestState { + self.followRequestState = followRequestState + } + } + public func update(transientFollowRequestState: MastodonFollowRequestState) { + if self.transientFollowRequestState != transientFollowRequestState { + self.transientFollowRequestState = transientFollowRequestState + } + } // sourcery:end } diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonFollowRequestState.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonFollowRequestState.swift new file mode 100644 index 000000000..c348d6cee --- /dev/null +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonFollowRequestState.swift @@ -0,0 +1,28 @@ +// +// MastodonFollowRequestState.swift +// +// +// Created by MainasuK on 2022-6-29. +// + +import SwiftUI + +public final class MastodonFollowRequestState: NSObject, Codable { + public let state: State + + public init( + state: State + ) { + self.state = state + } +} + +extension MastodonFollowRequestState { + public enum State: String, Codable { + case none + case isAccepting + case isAccept + case isRejecting + case isReject + } +} diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonNotificationType.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonNotificationType.swift index a982fda93..9e3029f26 100644 --- a/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonNotificationType.swift +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonNotificationType.swift @@ -21,7 +21,7 @@ public enum MastodonNotificationType: RawRepresentable { public init?(rawValue: String) { switch rawValue { case "follow": self = .follow - case "followRequest": self = .followRequest + case "follow_request": self = .followRequest case "mention": self = .mention case "reblog": self = .reblog case "favourite": self = .favourite @@ -34,7 +34,7 @@ public enum MastodonNotificationType: RawRepresentable { public var rawValue: String { switch self { case .follow: return "follow" - case .followRequest: return "followRequest" + case .followRequest: return "follow_request" case .mention: return "mention" case .reblog: return "reblog" case .favourite: return "favourite" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.colorset/Contents.json index 0c0c8af04..3a05fc4fe 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "55", - "green" : "44", - "red" : "40" + "blue" : "0x38", + "green" : "0x29", + "red" : "0x2B" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json index 8f42a585a..751d5998f 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/primary.reverse.colorset/Contents.json @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.216", - "green" : "0.173", - "red" : "0.157" + "blue" : "0x38", + "green" : "0x29", + "red" : "0x2B" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json index b23080b6b..6488a4e8c 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "133", - "green" : "112", - "red" : "102" + "blue" : "0x85", + "green" : "0x66", + "red" : "0x69" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/300.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/300.colorset/Contents.json new file mode 100644 index 000000000..e1a0ce662 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/300.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xC2", + "red" : "0xC2" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "0.761", + "red" : "0.761" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/700.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/700.colorset/Contents.json new file mode 100644 index 000000000..b9b9d31dd --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/700.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.733", + "green" : "0.110", + "red" : "0.263" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.733", + "green" : "0.110", + "red" : "0.263" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/Contents.json new file mode 100644 index 000000000..6e965652d --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Primary/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.colorset/Contents.json new file mode 100644 index 000000000..87b44e1c4 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xBB", + "green" : "0x1C", + "red" : "0x43" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0x99", + "red" : "0x99" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/Contents.json new file mode 100644 index 000000000..6e965652d --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.blue.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/brand.blue.colorset/Contents.json similarity index 100% rename from MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.blue.colorset/Contents.json rename to MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/brand.blue.colorset/Contents.json diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.blue.darken.20.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/brand.blue.darken.20.colorset/Contents.json similarity index 100% rename from MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/brand.blue.darken.20.colorset/Contents.json rename to MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/deprecated/brand.blue.darken.20.colorset/Contents.json diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/Contents.json new file mode 100644 index 000000000..6e965652d --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/checkmark.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/checkmark.imageset/Contents.json new file mode 100644 index 000000000..8879a2751 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/checkmark.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "checkmark.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/checkmark.imageset/checkmark.pdf b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/checkmark.imageset/checkmark.pdf new file mode 100644 index 000000000..c481ec4c5 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/checkmark.imageset/checkmark.pdf @@ -0,0 +1,76 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.250000 5.105469 cm +0.129412 0.129412 0.129412 scn +1.280330 5.924861 m +0.987437 6.217754 0.512563 6.217754 0.219670 5.924861 c +-0.073223 5.631968 -0.073223 5.157095 0.219670 4.864202 c +4.719670 0.364201 l +5.012563 0.071307 5.487436 0.071307 5.780330 0.364201 c +16.780331 11.364201 l +17.073223 11.657094 17.073223 12.131968 16.780331 12.424861 c +16.487438 12.717754 16.012562 12.717754 15.719669 12.424861 c +5.250000 1.955191 l +1.280330 5.924861 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 523 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000000613 00000 n +0000000635 00000 n +0000000808 00000 n +0000000882 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +941 +%%EOF \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/xmark.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/xmark.imageset/Contents.json new file mode 100644 index 000000000..df9d264a2 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/xmark.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "xmark.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/xmark.imageset/xmark.pdf b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/xmark.imageset/xmark.pdf new file mode 100644 index 000000000..6558a81f7 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Editing/xmark.imageset/xmark.pdf @@ -0,0 +1,89 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 4.250000 4.105469 cm +0.129412 0.129412 0.129412 scn +0.147052 15.340743 m +0.219670 15.424861 l +0.485936 15.691128 0.902600 15.715334 1.196212 15.497479 c +1.280330 15.424861 l +7.750000 8.955531 l +14.219669 15.424861 l +14.512563 15.717754 14.987437 15.717754 15.280331 15.424861 c +15.573224 15.131968 15.573224 14.657094 15.280331 14.364201 c +8.811000 7.894531 l +15.280331 1.424862 l +15.546597 1.158595 15.570804 0.741932 15.352949 0.448320 c +15.280331 0.364201 l +15.014064 0.097934 14.597401 0.073728 14.303789 0.291582 c +14.219669 0.364201 l +7.750000 6.833531 l +1.280330 0.364201 l +0.987437 0.071307 0.512563 0.071307 0.219670 0.364201 c +-0.073223 0.657094 -0.073223 1.131968 0.219670 1.424862 c +6.689000 7.894531 l +0.219670 14.364201 l +-0.046597 14.630467 -0.070803 15.047132 0.147052 15.340743 c +0.219670 15.424861 l +0.147052 15.340743 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 914 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001004 00000 n +0000001026 00000 n +0000001199 00000 n +0000001273 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1332 +%%EOF \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift b/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift index b594f9209..1536e1b0e 100644 --- a/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift +++ b/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift @@ -63,6 +63,10 @@ public enum Asset { public enum Poll { public static let disabled = ColorAsset(name: "Colors/Poll/disabled") } + public enum Primary { + public static let _300 = ColorAsset(name: "Colors/Primary/300") + public static let _700 = ColorAsset(name: "Colors/Primary/700") + } public enum Shadow { public static let searchCard = ColorAsset(name: "Colors/Shadow/SearchCard") } @@ -77,10 +81,13 @@ public enum Asset { public static let alertYellow = ColorAsset(name: "Colors/alert.yellow") public static let badgeBackground = ColorAsset(name: "Colors/badge.background") public static let battleshipGrey = ColorAsset(name: "Colors/battleshipGrey") - public static let brandBlue = ColorAsset(name: "Colors/brand.blue") - public static let brandBlueDarken20 = ColorAsset(name: "Colors/brand.blue.darken.20") + public static let brand = ColorAsset(name: "Colors/brand") public static let dangerBorder = ColorAsset(name: "Colors/danger.border") public static let danger = ColorAsset(name: "Colors/danger") + public enum Deprecated { + public static let brandBlue = ColorAsset(name: "Colors/deprecated/brand.blue") + public static let brandBlueDarken20 = ColorAsset(name: "Colors/deprecated/brand.blue.darken.20") + } public static let disabled = ColorAsset(name: "Colors/disabled") public static let inactive = ColorAsset(name: "Colors/inactive") public static let mediaTypeIndicotor = ColorAsset(name: "Colors/media.type.indicotor") @@ -94,6 +101,10 @@ public enum Asset { public enum Connectivity { public static let photoFillSplit = ImageAsset(name: "Connectivity/photo.fill.split") } + public enum Editing { + public static let checkmark = ImageAsset(name: "Editing/checkmark") + public static let xmark = ImageAsset(name: "Editing/xmark") + } public enum Human { public static let eyeCircleFill = ImageAsset(name: "Human/eye.circle.fill") public static let eyeSlashCircleFill = ImageAsset(name: "Human/eye.slash.circle.fill") diff --git a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift index 904f43a35..70a807fcb 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift +++ b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift @@ -612,6 +612,16 @@ public enum L10n { } } public enum Notification { + public enum FollowRequest { + /// Accept + public static let accept = L10n.tr("Localizable", "Scene.Notification.FollowRequest.Accept") + /// Accepted + public static let accepted = L10n.tr("Localizable", "Scene.Notification.FollowRequest.Accepted") + /// reject + public static let reject = L10n.tr("Localizable", "Scene.Notification.FollowRequest.Reject") + /// Rejected + public static let rejected = L10n.tr("Localizable", "Scene.Notification.FollowRequest.Rejected") + } public enum Keyobard { /// Show Everything public static let showEverything = L10n.tr("Localizable", "Scene.Notification.Keyobard.ShowEverything") diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings index d93d06d5e..3814c14a7 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings @@ -2,7 +2,7 @@ "Common.Alerts.BlockDomain.Title" = "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %@ بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يُزال جميع متابعيك المتواجدين فيه."; "Common.Alerts.CleanCache.Message" = "مُحِيَ ما مَساحَتُهُ %@ مِن ذاكِرَةِ التَّخزينِ المُؤقَّت بِنجاح."; "Common.Alerts.CleanCache.Title" = "مَحوُ ذاكِرَةِ التَّخزينِ المُؤقَّت"; -"Common.Alerts.Common.PleaseTryAgain" = "يُرجى المُحاولة مرة أُخرى."; +"Common.Alerts.Common.PleaseTryAgain" = "يُرجى المُحاوَلَةُ مُجَدَّدًا."; "Common.Alerts.Common.PleaseTryAgainLater" = "يُرجى المُحاولة مرة أُخرى لاحقًا."; "Common.Alerts.DeletePost.Message" = "هَل أنتَ مُتأكِدٌ مِن رَغبتِكَ فِي حَذفِ هَذَا المَنشُور؟"; "Common.Alerts.DeletePost.Title" = "هل أنت متأكد من رغبتك في حذف هذا المنشور؟"; @@ -17,13 +17,13 @@ "Common.Alerts.PublishPostFailure.Title" = "إخفاق في عمليَّة النشر"; "Common.Alerts.SavePhotoFailure.Message" = "يُرجى إتاحة إذن الوصول إلى مكتبة الصور لحفظ الصورة."; "Common.Alerts.SavePhotoFailure.Title" = "إخفاق في حفظ الصورة"; -"Common.Alerts.ServerError.Title" = "خطأ في الخادم"; +"Common.Alerts.ServerError.Title" = "خَطَأٌ فِي الخادِم"; "Common.Alerts.SignOut.Confirm" = "تَسجيلُ الخُروج"; "Common.Alerts.SignOut.Message" = "هل أنت متأكد من رغبتك في تسجيل الخُروج؟"; "Common.Alerts.SignOut.Title" = "تَسجيلُ الخُروج"; -"Common.Alerts.SignUpFailure.Title" = "إخفاق في التسجيل"; -"Common.Alerts.VoteFailure.PollEnded" = "انتهى استطلاع الرأي"; -"Common.Alerts.VoteFailure.Title" = "إخفاق في التصويت"; +"Common.Alerts.SignUpFailure.Title" = "إخفاقٌ فِي التَّسجيل"; +"Common.Alerts.VoteFailure.PollEnded" = "اِنتَهَى اِستِطلاعُ الرَّأي"; +"Common.Alerts.VoteFailure.Title" = "إخفاقٌ فِي التَّصويت"; "Common.Controls.Actions.Add" = "إضافة"; "Common.Controls.Actions.Back" = "العودة"; "Common.Controls.Actions.BlockDomain" = "حظر %@"; @@ -223,6 +223,10 @@ "Scene.HomeTimeline.NavigationBarState.Published" = "تمَّ النَّشر!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "يَجري نَشر المُشارَكَة..."; "Scene.HomeTimeline.Title" = "الرَّئِيسَة"; +"Scene.Notification.FollowRequest.Accept" = "قَبُول"; +"Scene.Notification.FollowRequest.Accepted" = "مَقبُول"; +"Scene.Notification.FollowRequest.Reject" = "رَفض"; +"Scene.Notification.FollowRequest.Rejected" = "مَرفُوض"; "Scene.Notification.Keyobard.ShowEverything" = "أظْهِر كُلَّ شَيء"; "Scene.Notification.Keyobard.ShowMentions" = "أظْهِر الإشارَات"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "فَضَّلَ مَنشُورَك"; @@ -263,9 +267,9 @@ "Scene.RebloggedBy.Title" = "اُعيدَ تَدوينَهُ بِواسِطَةِ"; "Scene.Register.Error.Item.Agreement" = "الاِتِّفاقيَّة"; "Scene.Register.Error.Item.Email" = "البريد الإلكتروني"; -"Scene.Register.Error.Item.Locale" = "اللغة المحلية"; +"Scene.Register.Error.Item.Locale" = "اللُّغَة"; "Scene.Register.Error.Item.Password" = "الرمز السري"; -"Scene.Register.Error.Item.Reason" = "السبب"; +"Scene.Register.Error.Item.Reason" = "السَّبَب"; "Scene.Register.Error.Item.Username" = "اِسمُ المُستَخدِم"; "Scene.Register.Error.Reason.Accepted" = "يجب أن يُقبل %@"; "Scene.Register.Error.Reason.Blank" = "%@ مَطلوب"; @@ -274,10 +278,10 @@ "Scene.Register.Error.Reason.Invalid" = "%@ غير صالح"; "Scene.Register.Error.Reason.Reserved" = "إنَّ %@ عبارة عن كلمة مفتاحيَّة محجوزة"; "Scene.Register.Error.Reason.Taken" = "إنَّ %@ مُستخدَمٌ بالفعل"; -"Scene.Register.Error.Reason.TooLong" = "%@ طويل جداً"; -"Scene.Register.Error.Reason.TooShort" = "%@ قصير جدًا"; +"Scene.Register.Error.Reason.TooLong" = "%@ طَويلٌ جِدًّا"; +"Scene.Register.Error.Reason.TooShort" = "%@ قَصِيرٌ جِدًا"; "Scene.Register.Error.Reason.Unreachable" = "يبدوا أنَّ %@ غير موجود"; -"Scene.Register.Error.Special.EmailInvalid" = "هذا عنوان بريد إلكتروني غير صالح"; +"Scene.Register.Error.Special.EmailInvalid" = "عُنوانُ البَريدِ الاِلِكتُرُونيّ هَذَا غَيرُ صَالِح"; "Scene.Register.Error.Special.PasswordTooShort" = "رمز السر قصير جدًا (يجب أن يتكون من ثمان خانات على الأقل)"; "Scene.Register.Error.Special.UsernameInvalid" = "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط"; "Scene.Register.Error.Special.UsernameTooLong" = "اِسم المُستَخدِم طويل جداً (يَجِبُ ألّا يكون أطول من ثلاثين خانة)"; @@ -356,28 +360,28 @@ "Scene.Search.Searching.Segment.Posts" = "مَنشُورات"; "Scene.Search.Title" = "البَحث"; "Scene.ServerPicker.Button.Category.Academia" = "أكاديمي"; -"Scene.ServerPicker.Button.Category.Activism" = "النشطاء"; -"Scene.ServerPicker.Button.Category.All" = "الكل"; -"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "الفئة: الكل"; -"Scene.ServerPicker.Button.Category.Art" = "فنون"; -"Scene.ServerPicker.Button.Category.Food" = "الطعام"; -"Scene.ServerPicker.Button.Category.Furry" = "مكسو بالفرو"; -"Scene.ServerPicker.Button.Category.Games" = "ألعاب"; -"Scene.ServerPicker.Button.Category.General" = "عام"; -"Scene.ServerPicker.Button.Category.Journalism" = "صحافة"; -"Scene.ServerPicker.Button.Category.Lgbt" = "مجتمع الشواذ"; -"Scene.ServerPicker.Button.Category.Music" = "موسيقى"; +"Scene.ServerPicker.Button.Category.Activism" = "نُشَطاء"; +"Scene.ServerPicker.Button.Category.All" = "الكُل"; +"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "الفِئَة: الكُل"; +"Scene.ServerPicker.Button.Category.Art" = "فُنون"; +"Scene.ServerPicker.Button.Category.Food" = "طَعام"; +"Scene.ServerPicker.Button.Category.Furry" = "مَكسُوٌ بِالفَرو"; +"Scene.ServerPicker.Button.Category.Games" = "ألعَاب"; +"Scene.ServerPicker.Button.Category.General" = "عَام"; +"Scene.ServerPicker.Button.Category.Journalism" = "صَحافة"; +"Scene.ServerPicker.Button.Category.Lgbt" = "مَخَانِيث"; +"Scene.ServerPicker.Button.Category.Music" = "مُوسيقى"; "Scene.ServerPicker.Button.Category.Regional" = "إقليمي"; -"Scene.ServerPicker.Button.Category.Tech" = "تقنية"; -"Scene.ServerPicker.Button.SeeLess" = "عرض عناصر أقل"; -"Scene.ServerPicker.Button.SeeMore" = "عرض عناصر أكثر"; +"Scene.ServerPicker.Button.Category.Tech" = "تَقنِيَة"; +"Scene.ServerPicker.Button.SeeLess" = "عَرضُ عَناصِرٍ أقَل"; +"Scene.ServerPicker.Button.SeeMore" = "عَرضُ عَناصِرٍ أكثَر"; "Scene.ServerPicker.EmptyState.BadNetwork" = "حدث خطأٌ ما أثناء تحميل البيانات. تحقَّق من اتصالك بالإنترنت."; "Scene.ServerPicker.EmptyState.FindingServers" = "يجري إيجاد خوادم متوفِّرَة..."; "Scene.ServerPicker.EmptyState.NoResults" = "لا توجد نتائج"; "Scene.ServerPicker.Input.Placeholder" = "اِبحَث عن خادِم أو انضم إلى آخر خاص بك..."; "Scene.ServerPicker.Input.SearchServersOrEnterUrl" = "اِبحَث فِي الخَوادِم أو أدخِل رابِط"; "Scene.ServerPicker.Label.Category" = "الفئة"; -"Scene.ServerPicker.Label.Language" = "اللُّغة"; +"Scene.ServerPicker.Label.Language" = "اللُّغَة"; "Scene.ServerPicker.Label.Users" = "مُستَخدِم"; "Scene.ServerPicker.Subtitle" = "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام."; "Scene.ServerPicker.SubtitleExtend" = "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام. تُشغَّل جميعُ المجتمعِ مِن قِبَلِ مُنظمَةٍ أو فردٍ مُستقلٍ تمامًا."; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings index e6a706391..5e11b147a 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings @@ -223,6 +223,10 @@ carregat a Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Publicat!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "S'està publicant..."; "Scene.HomeTimeline.Title" = "Inici"; +"Scene.Notification.FollowRequest.Accept" = "Acceptar"; +"Scene.Notification.FollowRequest.Accepted" = "Acceptat"; +"Scene.Notification.FollowRequest.Reject" = "rebutjar"; +"Scene.Notification.FollowRequest.Rejected" = "Rebutjat"; "Scene.Notification.Keyobard.ShowEverything" = "Mostrar-ho tot"; "Scene.Notification.Keyobard.ShowMentions" = "Mostrar Mencions"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "ha afavorit la teva publicació"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ckb.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ckb.lproj/Localizable.strings index f87c284d9..3653f3810 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ckb.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ckb.lproj/Localizable.strings @@ -222,6 +222,10 @@ "Scene.HomeTimeline.NavigationBarState.Published" = "بڵاوکرایەوە!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "پۆستەکە بڵاو دەکرێتەوە..."; "Scene.HomeTimeline.Title" = "ماڵەوە"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "هەموو شتێک نیشان بدە"; "Scene.Notification.Keyobard.ShowMentions" = "ئاماژەکان نیشان بدە"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "پۆستەکەتی بەدڵ بوو"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings index 92e9fb074..3b1622945 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings @@ -223,6 +223,10 @@ kann nicht auf Mastodon hochgeladen werden."; "Scene.HomeTimeline.NavigationBarState.Published" = "Veröffentlicht!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Beitrag wird veröffentlicht..."; "Scene.HomeTimeline.Title" = "Startseite"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Alles anzeigen"; "Scene.Notification.Keyobard.ShowMentions" = "Erwähnungen anzeigen"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "hat deinen Beitrag favorisiert"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings index 6c6dcc72b..12df948fc 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings @@ -223,6 +223,10 @@ uploaded to Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Published!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Publishing post..."; "Scene.HomeTimeline.Title" = "Home"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Show Everything"; "Scene.Notification.Keyobard.ShowMentions" = "Show Mentions"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings index 4fe1c35c3..0e6ba2582 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings @@ -108,7 +108,7 @@ Por favor, revise su conexión a internet."; "Common.Controls.Status.MediaContentWarning" = "Pulsa en cualquier sitio para mostrar"; "Common.Controls.Status.Poll.Closed" = "Cerrado"; "Common.Controls.Status.Poll.Vote" = "Vota"; -"Common.Controls.Status.SensitiveContent" = "Sensitive Content"; +"Common.Controls.Status.SensitiveContent" = "Contenido sensible"; "Common.Controls.Status.ShowPost" = "Mostrar Publicación"; "Common.Controls.Status.ShowUserProfile" = "Mostrar perfil del usuario"; "Common.Controls.Status.Tag.Email" = "E-mail"; @@ -201,29 +201,33 @@ subirse a Mastodon."; "Scene.ConfirmEmail.OpenEmailApp.Title" = "Revisa tu bandeja de entrada."; "Scene.ConfirmEmail.Subtitle" = "Te acabamos de enviar un correo a %@, pulsa en el enlace para confirmar tu cuenta."; -"Scene.ConfirmEmail.TapTheLinkWeEmailedToYouToVerifyYourAccount" = "Tap the link we emailed to you to verify your account"; +"Scene.ConfirmEmail.TapTheLinkWeEmailedToYouToVerifyYourAccount" = "Toca el enlace que te enviamos por correo electrónico para verificar tu cuenta"; "Scene.ConfirmEmail.Title" = "Una última cosa."; -"Scene.Discovery.Intro" = "These are the posts gaining traction in your corner of Mastodon."; -"Scene.Discovery.Tabs.Community" = "Community"; +"Scene.Discovery.Intro" = "Estas son las publicaciones que están ganando tracción en tu rincón de Mastodon."; +"Scene.Discovery.Tabs.Community" = "Comunidad"; "Scene.Discovery.Tabs.ForYou" = "Para Ti"; "Scene.Discovery.Tabs.Hashtags" = "Etiquetas"; "Scene.Discovery.Tabs.News" = "Noticias"; "Scene.Discovery.Tabs.Posts" = "Publicaciones"; -"Scene.Familiarfollowers.FollowedByNames" = "Followed by %@"; -"Scene.Familiarfollowers.Title" = "Followers you familiar"; +"Scene.Familiarfollowers.FollowedByNames" = "Seguido por %@"; +"Scene.Familiarfollowers.Title" = "Seguidores que conoces"; "Scene.Favorite.Title" = "Tus Favoritos"; -"Scene.FavoritedBy.Title" = "Favorited By"; +"Scene.FavoritedBy.Title" = "Hecho favorito por"; "Scene.Follower.Footer" = "No se muestran los seguidores de otros servidores."; -"Scene.Follower.Title" = "follower"; +"Scene.Follower.Title" = "seguidor"; "Scene.Following.Footer" = "No se muestran los seguidos de otros servidores."; -"Scene.Following.Title" = "following"; -"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoHint" = "Tap to scroll to top and tap again to previous location"; -"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoLabel" = "Logo Button"; +"Scene.Following.Title" = "siguiendo"; +"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoHint" = "Toca para desplazarte hacia arriba y toca de nuevo para la localización anterior"; +"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoLabel" = "Botón del logo"; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ver nuevas publicaciones"; "Scene.HomeTimeline.NavigationBarState.Offline" = "Sin Conexión"; "Scene.HomeTimeline.NavigationBarState.Published" = "¡Publicado!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Publicación en curso..."; "Scene.HomeTimeline.Title" = "Inicio"; +"Scene.Notification.FollowRequest.Accept" = "Aceptar"; +"Scene.Notification.FollowRequest.Accepted" = "Aceptado"; +"Scene.Notification.FollowRequest.Reject" = "rechazar"; +"Scene.Notification.FollowRequest.Rejected" = "Rechazado"; "Scene.Notification.Keyobard.ShowEverything" = "Mostrar Todo"; "Scene.Notification.Keyobard.ShowMentions" = "Mostrar Menciones"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "ha marcado como favorita tu publicación"; @@ -247,7 +251,7 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.Profile.Fields.AddRow" = "Añadir Fila"; "Scene.Profile.Fields.Placeholder.Content" = "Contenido"; "Scene.Profile.Fields.Placeholder.Label" = "Nombre para el campo"; -"Scene.Profile.Header.FollowsYou" = "Follows You"; +"Scene.Profile.Header.FollowsYou" = "Te sigue"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirmar para bloquear a %@"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bloquear cuenta"; "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirmar para silenciar %@"; @@ -261,7 +265,7 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.Profile.SegmentedControl.Posts" = "Publicaciones"; "Scene.Profile.SegmentedControl.PostsAndReplies" = "Publicaciones y respuestas"; "Scene.Profile.SegmentedControl.Replies" = "Respuestas"; -"Scene.RebloggedBy.Title" = "Reblogged By"; +"Scene.RebloggedBy.Title" = "Reblogueado por"; "Scene.Register.Error.Item.Agreement" = "Aceptación"; "Scene.Register.Error.Item.Email" = "Correo electrónico"; "Scene.Register.Error.Item.Locale" = "Idioma"; @@ -294,7 +298,7 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.Register.Input.Password.Require" = "Tu contraseña debe contener como mínimo:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Este nombre de usuario ya está en uso."; "Scene.Register.Input.Username.Placeholder" = "nombre de usuario"; -"Scene.Register.LetsGetYouSetUpOnDomain" = "Let’s get you set up on %@"; +"Scene.Register.LetsGetYouSetUpOnDomain" = "Deja que te preparemos en %@"; "Scene.Register.Title" = "Háblanos de ti."; "Scene.Report.Content1" = "¿Hay alguna otra publicación que te gustaría añadir al reporte?"; "Scene.Report.Content2" = "¿Hay algo que los moderadores deberían saber acerca de este reporte?"; @@ -304,38 +308,38 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.Report.SkipToSend" = "Enviar sin comentarios"; "Scene.Report.Step1" = "Paso 1 de 2"; "Scene.Report.Step2" = "Paso 2 de 2"; -"Scene.Report.StepFinal.BlockUser" = "Block %@"; -"Scene.Report.StepFinal.DontWantToSeeThis" = "Don’t want to see this?"; -"Scene.Report.StepFinal.MuteUser" = "Mute %@"; -"Scene.Report.StepFinal.TheyWillNoLongerBeAbleToFollowOrSeeYourPostsButTheyCanSeeIfTheyveBeenBlocked" = "They will no longer be able to follow or see your posts, but they can see if they’ve been blocked."; -"Scene.Report.StepFinal.Unfollow" = "Unfollow"; -"Scene.Report.StepFinal.UnfollowUser" = "Unfollow %@"; -"Scene.Report.StepFinal.Unfollowed" = "Unfollowed"; -"Scene.Report.StepFinal.WhenYouSeeSomethingYouDontLikeOnMastodonYouCanRemoveThePersonFromYourExperience." = "When you see something you don’t like on Mastodon, you can remove the person from your experience."; -"Scene.Report.StepFinal.WhileWeReviewThisYouCanTakeActionAgainstUser" = "While we review this, you can take action against %@"; -"Scene.Report.StepFinal.YouWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted" = "You won’t see their posts or reblogs in your home feed. They won’t know they’ve been muted."; -"Scene.Report.StepFour.IsThereAnythingElseWeShouldKnow" = "Is there anything else we should know?"; -"Scene.Report.StepFour.Step4Of4" = "Step 4 of 4"; -"Scene.Report.StepOne.IDontLikeIt" = "I don’t like it"; -"Scene.Report.StepOne.ItIsNotSomethingYouWantToSee" = "It is not something you want to see"; -"Scene.Report.StepOne.ItViolatesServerRules" = "It violates server rules"; -"Scene.Report.StepOne.ItsSomethingElse" = "It’s something else"; -"Scene.Report.StepOne.ItsSpam" = "It’s spam"; -"Scene.Report.StepOne.MaliciousLinksFakeEngagementOrRepetetiveReplies" = "Malicious links, fake engagement, or repetetive replies"; -"Scene.Report.StepOne.SelectTheBestMatch" = "Select the best match"; -"Scene.Report.StepOne.Step1Of4" = "Step 1 of 4"; -"Scene.Report.StepOne.TheIssueDoesNotFitIntoOtherCategories" = "The issue does not fit into other categories"; -"Scene.Report.StepOne.WhatsWrongWithThisAccount" = "What's wrong with this account?"; -"Scene.Report.StepOne.WhatsWrongWithThisPost" = "What's wrong with this post?"; -"Scene.Report.StepOne.WhatsWrongWithThisUsername" = "What's wrong with %@?"; -"Scene.Report.StepOne.YouAreAwareThatItBreaksSpecificRules" = "You are aware that it breaks specific rules"; -"Scene.Report.StepThree.AreThereAnyPostsThatBackUpThisReport" = "Are there any posts that back up this report?"; -"Scene.Report.StepThree.SelectAllThatApply" = "Select all that apply"; -"Scene.Report.StepThree.Step3Of4" = "Step 3 of 4"; -"Scene.Report.StepTwo.IJustDon’tLikeIt" = "I just don’t like it"; -"Scene.Report.StepTwo.SelectAllThatApply" = "Select all that apply"; -"Scene.Report.StepTwo.Step2Of4" = "Step 2 of 4"; -"Scene.Report.StepTwo.WhichRulesAreBeingViolated" = "Which rules are being violated?"; +"Scene.Report.StepFinal.BlockUser" = "Bloquear a %@"; +"Scene.Report.StepFinal.DontWantToSeeThis" = "¿No quieres ver esto?"; +"Scene.Report.StepFinal.MuteUser" = "Silenciar a %@"; +"Scene.Report.StepFinal.TheyWillNoLongerBeAbleToFollowOrSeeYourPostsButTheyCanSeeIfTheyveBeenBlocked" = "Ya no podrán ser capaces de seguirte o ver tus publicaciones, pero pueden ver si han sido bloqueados."; +"Scene.Report.StepFinal.Unfollow" = "Dejar de seguir"; +"Scene.Report.StepFinal.UnfollowUser" = "Dejar de seguir a %@"; +"Scene.Report.StepFinal.Unfollowed" = "Ha dejado de seguirte"; +"Scene.Report.StepFinal.WhenYouSeeSomethingYouDontLikeOnMastodonYouCanRemoveThePersonFromYourExperience." = "Cuando veas algo que no te gusta en Mastodon, puedes quitar a la persona de tu experiencia."; +"Scene.Report.StepFinal.WhileWeReviewThisYouCanTakeActionAgainstUser" = "Mientras revisamos esto, puedes tomar medidas contra %@"; +"Scene.Report.StepFinal.YouWontSeeTheirPostsOrReblogsInYourHomeFeedTheyWontKnowTheyVeBeenMuted" = "No verás sus publicaciones o reblogueos en tu línea temporal. No sabrán que han sido silenciados."; +"Scene.Report.StepFour.IsThereAnythingElseWeShouldKnow" = "¿Hay algo más que deberíamos saber?"; +"Scene.Report.StepFour.Step4Of4" = "Paso 4 de 4"; +"Scene.Report.StepOne.IDontLikeIt" = "No me gusta"; +"Scene.Report.StepOne.ItIsNotSomethingYouWantToSee" = "No es algo que quieras ver"; +"Scene.Report.StepOne.ItViolatesServerRules" = "Viola las reglas del servidor"; +"Scene.Report.StepOne.ItsSomethingElse" = "Es algo más"; +"Scene.Report.StepOne.ItsSpam" = "Es spam"; +"Scene.Report.StepOne.MaliciousLinksFakeEngagementOrRepetetiveReplies" = "Enlaces maliciosos, compromisos falsos o respuestas repetitivas"; +"Scene.Report.StepOne.SelectTheBestMatch" = "Selecciona la mejor opción"; +"Scene.Report.StepOne.Step1Of4" = "Paso 1 de 4"; +"Scene.Report.StepOne.TheIssueDoesNotFitIntoOtherCategories" = "El problema no encaja en otras categorías"; +"Scene.Report.StepOne.WhatsWrongWithThisAccount" = "¿Qué hay de malo con esta cuenta?"; +"Scene.Report.StepOne.WhatsWrongWithThisPost" = "¿Qué hay de malo con esta publicación?"; +"Scene.Report.StepOne.WhatsWrongWithThisUsername" = "¿Qué hay de malo con %@?"; +"Scene.Report.StepOne.YouAreAwareThatItBreaksSpecificRules" = "Eres consciente de que infringe las normas específicas"; +"Scene.Report.StepThree.AreThereAnyPostsThatBackUpThisReport" = "¿Hay alguna publicación que respalde este informe?"; +"Scene.Report.StepThree.SelectAllThatApply" = "Selecciona todos los que correspondan"; +"Scene.Report.StepThree.Step3Of4" = "Paso 3 de 4"; +"Scene.Report.StepTwo.IJustDon’tLikeIt" = "Solamente no me gusta"; +"Scene.Report.StepTwo.SelectAllThatApply" = "Selecciona todos los que correspondan"; +"Scene.Report.StepTwo.Step2Of4" = "Paso 2 de 4"; +"Scene.Report.StepTwo.WhichRulesAreBeingViolated" = "¿Qué normas se están violando?"; "Scene.Report.TextPlaceholder" = "Escribe o pega comentarios adicionales"; "Scene.Report.Title" = "Reportar %@"; "Scene.Report.TitleReport" = "Reportar"; @@ -376,7 +380,7 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.ServerPicker.EmptyState.FindingServers" = "Encontrando servidores disponibles..."; "Scene.ServerPicker.EmptyState.NoResults" = "Sin resultados"; "Scene.ServerPicker.Input.Placeholder" = "Encuentra un servidor o únete al tuyo propio..."; -"Scene.ServerPicker.Input.SearchServersOrEnterUrl" = "Search servers or enter URL"; +"Scene.ServerPicker.Input.SearchServersOrEnterUrl" = "Buscar servidores o introducir la URL"; "Scene.ServerPicker.Label.Category" = "CATEGORÍA"; "Scene.ServerPicker.Label.Language" = "IDIOMA"; "Scene.ServerPicker.Label.Users" = "USUARIOS"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict index 05bcff142..def3d7bba 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict @@ -72,9 +72,9 @@ NSStringFormatValueTypeKey ld one - Followed by %1$@, and another mutual + Seguido por %1$@ y otro mutuo other - Followed by %1$@, and %ld mutuals + Seguido por %1$@ y %ld mutuos plural.count.metric_formatted.post diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/eu.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/eu.lproj/Localizable.strings index 3d25819cf..aad4ad238 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/eu.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/eu.lproj/Localizable.strings @@ -223,6 +223,10 @@ Mastodonera igo."; "Scene.HomeTimeline.NavigationBarState.Published" = "Argitaratua!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Bidalketa argitaratzen..."; "Scene.HomeTimeline.Title" = "Hasiera"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Erakutsi guztia"; "Scene.Notification.Keyobard.ShowMentions" = "Erakutsi aipamenak"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "(e)k zure bidalketa gogoko du"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/fi.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/fi.lproj/Localizable.strings index 546048595..3987e7749 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/fi.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/fi.lproj/Localizable.strings @@ -223,6 +223,10 @@ uploaded to Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Julkaistu!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Julkaistaan julkaisua..."; "Scene.HomeTimeline.Title" = "Koti"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Näytä kaikki"; "Scene.Notification.Keyobard.ShowMentions" = "Näytä maininnat"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings index 2136ca90a..d0a964b54 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings @@ -223,6 +223,10 @@ téléversé sur Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Publié!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Publication en cours ..."; "Scene.HomeTimeline.Title" = "Accueil"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Tout Afficher"; "Scene.Notification.Keyobard.ShowMentions" = "Afficher les mentions"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "a ajouté votre message à ses favoris"; @@ -246,7 +250,7 @@ téléversé sur Mastodon."; "Scene.Profile.Fields.AddRow" = "Ajouter une rangée"; "Scene.Profile.Fields.Placeholder.Content" = "Contenu"; "Scene.Profile.Fields.Placeholder.Label" = "Étiquette"; -"Scene.Profile.Header.FollowsYou" = "Follows You"; +"Scene.Profile.Header.FollowsYou" = "Vous suit"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirmer le blocage de %@"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bloquer le compte"; "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Êtes-vous sûr de vouloir mettre en sourdine %@"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/gd.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/gd.lproj/Localizable.strings index 4f8479bda..1bb94dc2c 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/gd.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/gd.lproj/Localizable.strings @@ -224,6 +224,10 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.HomeTimeline.NavigationBarState.Published" = "Chaidh fhoillseachadh!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "A’ foillseachadh a’ phuist…"; "Scene.HomeTimeline.Title" = "Dachaigh"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Seall a h-uile càil"; "Scene.Notification.Keyobard.ShowMentions" = "Seall na h-iomraidhean"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "– is annsa leotha am post agad"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/gl.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/gl.lproj/Localizable.strings index aa4bea028..dfb88a006 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/gl.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/gl.lproj/Localizable.strings @@ -223,6 +223,10 @@ ser subido a Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Publicado!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Publicando..."; "Scene.HomeTimeline.Title" = "Inicio"; +"Scene.Notification.FollowRequest.Accept" = "Aceptar"; +"Scene.Notification.FollowRequest.Accepted" = "Aceptada"; +"Scene.Notification.FollowRequest.Reject" = "rexeitar"; +"Scene.Notification.FollowRequest.Rejected" = "Rexeitada"; "Scene.Notification.Keyobard.ShowEverything" = "Mostrar Todo"; "Scene.Notification.Keyobard.ShowMentions" = "Mostrar mencións"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "marcou a túa publicación como favorita"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/it.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/it.lproj/Localizable.strings index fad6c654e..cff8374cf 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/it.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/it.lproj/Localizable.strings @@ -223,6 +223,10 @@ caricato su Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Pubblicato!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Pubblicazione post..."; "Scene.HomeTimeline.Title" = "Inizio"; +"Scene.Notification.FollowRequest.Accept" = "Accetta"; +"Scene.Notification.FollowRequest.Accepted" = "Richiesta accettata"; +"Scene.Notification.FollowRequest.Reject" = "rifiuta"; +"Scene.Notification.FollowRequest.Rejected" = "Richiesta rifiutata"; "Scene.Notification.Keyobard.ShowEverything" = "Mostra Tutto"; "Scene.Notification.Keyobard.ShowMentions" = "Mostra Menzioni"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "ha apprezzato il tuo post"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings index b8fcca439..de61ef1d9 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings @@ -106,9 +106,9 @@ "Common.Controls.Status.Actions.Unreblog" = "ブーストを戻す"; "Common.Controls.Status.ContentWarning" = "コンテンツ警告"; "Common.Controls.Status.MediaContentWarning" = "どこかをタップして表示"; -"Common.Controls.Status.Poll.Closed" = "クローズド"; +"Common.Controls.Status.Poll.Closed" = "終了"; "Common.Controls.Status.Poll.Vote" = "投票"; -"Common.Controls.Status.SensitiveContent" = "Sensitive Content"; +"Common.Controls.Status.SensitiveContent" = "閲覧注意"; "Common.Controls.Status.ShowPost" = "投稿を見る"; "Common.Controls.Status.ShowUserProfile" = "プロフィールを見る"; "Common.Controls.Status.Tag.Email" = "メール"; @@ -186,7 +186,7 @@ "Scene.Compose.Visibility.Public" = "パブリック"; "Scene.Compose.Visibility.Unlisted" = "非表示"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "メールアプリを開く"; -"Scene.ConfirmEmail.Button.Resend" = "Resend"; +"Scene.ConfirmEmail.Button.Resend" = "再送信"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "メールアドレスが正しいかどうか、また、迷惑メールフォルダに入っていないかどうかも確認してください。"; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "もう一度メールを送信"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "メールをチェックしてください"; @@ -208,24 +208,28 @@ "Scene.Favorite.Title" = "お気に入り"; "Scene.FavoritedBy.Title" = "Favorited By"; "Scene.Follower.Footer" = "他のサーバーからのフォロワーは表示されません。"; -"Scene.Follower.Title" = "follower"; +"Scene.Follower.Title" = "フォロワー"; "Scene.Following.Footer" = "他のサーバーにいるフォローは表示されません。"; -"Scene.Following.Title" = "following"; -"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoHint" = "Tap to scroll to top and tap again to previous location"; -"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoLabel" = "Logo Button"; +"Scene.Following.Title" = "フォロー"; +"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoHint" = "タップすると一番上までスクロールし、もう一度タップすると元の場所に戻ります"; +"Scene.HomeTimeline.NavigationBarState.Accessibility.LogoLabel" = "ロゴボタン"; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "新しい投稿を見る"; "Scene.HomeTimeline.NavigationBarState.Offline" = "オフライン"; "Scene.HomeTimeline.NavigationBarState.Published" = "投稿しました!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "投稿中..."; "Scene.HomeTimeline.Title" = "ホーム"; +"Scene.Notification.FollowRequest.Accept" = "承認"; +"Scene.Notification.FollowRequest.Accepted" = "承諾済み"; +"Scene.Notification.FollowRequest.Reject" = "拒否"; +"Scene.Notification.FollowRequest.Rejected" = "拒否済み"; "Scene.Notification.Keyobard.ShowEverything" = "すべて見る"; "Scene.Notification.Keyobard.ShowMentions" = "メンションを見る"; -"Scene.Notification.NotificationDescription.FavoritedYourPost" = "さんがあなたの投稿をお気に入りに登録しました"; -"Scene.Notification.NotificationDescription.FollowedYou" = "さんにフォローされました"; -"Scene.Notification.NotificationDescription.MentionedYou" = "さんがあなたに返信しました"; -"Scene.Notification.NotificationDescription.PollHasEnded" = "アンケートが終了しました"; -"Scene.Notification.NotificationDescription.RebloggedYourPost" = "さんがあなたの投稿をブーストしました"; -"Scene.Notification.NotificationDescription.RequestToFollowYou" = "さんがあなたにフォローリクエストしました"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "がお気に入りに登録"; +"Scene.Notification.NotificationDescription.FollowedYou" = "にフォローされました"; +"Scene.Notification.NotificationDescription.MentionedYou" = "にメンションされました"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "のアンケートが終了"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "がブースト"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "からのフォローリクエスト"; "Scene.Notification.Title.Everything" = "すべて"; "Scene.Notification.Title.Mentions" = "メンション"; "Scene.Preview.Keyboard.ClosePreview" = "プレビューを閉じる"; @@ -241,13 +245,13 @@ "Scene.Profile.Fields.AddRow" = "行追加"; "Scene.Profile.Fields.Placeholder.Content" = "コンテンツ"; "Scene.Profile.Fields.Placeholder.Label" = "ラベル"; -"Scene.Profile.Header.FollowsYou" = "Follows You"; -"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; -"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Unblock Account"; +"Scene.Profile.Header.FollowsYou" = "フォローされています"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "%@をブロックしますか?"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "アカウントをブロック"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "%@をミュートしますか?"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "アカウントをミュート"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "%@のブロックを解除しますか?"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "アカウントのブロックを解除"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "%@をミュートしますか?"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "ミュートを解除"; "Scene.Profile.SegmentedControl.About" = "概要"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict index 054b8cded..cbc999738 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict @@ -92,7 +92,7 @@ NSStringFormatValueTypeKey ld other - %ld media + %ld件のメディア plural.count.post @@ -106,7 +106,7 @@ NSStringFormatValueTypeKey ld other - %ld posts + %ld件の投稿 plural.count.favorite @@ -148,7 +148,7 @@ NSStringFormatValueTypeKey ld other - %ld replies + %ld件の返信 plural.count.vote @@ -176,7 +176,7 @@ NSStringFormatValueTypeKey ld other - %ld voters + %ld人の投票 plural.people_talking @@ -316,7 +316,7 @@ NSStringFormatValueTypeKey ld other - %ld 年前 + %ld年前 date.month.ago.abbr diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/kab.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/kab.lproj/Localizable.strings index d382a5d57..4db503495 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/kab.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/kab.lproj/Localizable.strings @@ -223,6 +223,10 @@ Ad d-yettwasali ɣef Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Yettwasuffeɣ!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Asuffeɣ tasuffeɣt..."; "Scene.HomeTimeline.Title" = "Agejdan"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Sken yal taɣawsa"; "Scene.Notification.Keyobard.ShowMentions" = "Sken tisedmirin"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "yesmenyef tasuffeɣt-ik·im"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings index b626f017b..a77923674 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings @@ -224,6 +224,10 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "Scene.HomeTimeline.NavigationBarState.Published" = "Hate weşandin!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Şandî tê weşandin..."; "Scene.HomeTimeline.Title" = "Serrûpel"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Her tiştî nîşan bide"; "Scene.Notification.Keyobard.ShowMentions" = "Qalkirinan nîşan bike"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "şandiya te hez kir"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings index e149c42e8..cea8ce7e7 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings @@ -218,6 +218,10 @@ klik op de link om uw account te bevestigen."; "Scene.HomeTimeline.NavigationBarState.Published" = "Gepubliceerd!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Bericht publiceren..."; "Scene.HomeTimeline.Title" = "Start"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Alles weergeven"; "Scene.Notification.Keyobard.ShowMentions" = "Vermeldingen weergeven"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "heeft je bericht als favoriet gemrkeerd"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings index 80f8eaf8d..8b5adf626 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings @@ -234,6 +234,10 @@ "Scene.HomeTimeline.NavigationBarState.Published" = "Опубликовано!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Публикуем пост..."; "Scene.HomeTimeline.Title" = "Главная"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Показать все"; "Scene.Notification.Keyobard.ShowMentions" = "Показать упоминания"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/sv.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/sv.lproj/Localizable.strings index 7c13cdcc2..51b18d908 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/sv.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/sv.lproj/Localizable.strings @@ -223,6 +223,10 @@ laddas upp till Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Publicerat!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Publicerar inlägget..."; "Scene.HomeTimeline.Title" = "Hem"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Visa allt"; "Scene.Notification.Keyobard.ShowMentions" = "Visa omnämningar"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "favoriserade ditt inlägg"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings index 4b52b7e3c..2b67fa50d 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings @@ -223,6 +223,10 @@ "Scene.HomeTimeline.NavigationBarState.Published" = "เผยแพร่แล้ว!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "กำลังเผยแพร่โพสต์..."; "Scene.HomeTimeline.Title" = "หน้าแรก"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "แสดงทุกอย่าง"; "Scene.Notification.Keyobard.ShowMentions" = "แสดงการกล่าวถึง"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "ได้ชื่นชอบโพสต์ของคุณ"; @@ -246,7 +250,7 @@ "Scene.Profile.Fields.AddRow" = "เพิ่มแถว"; "Scene.Profile.Fields.Placeholder.Content" = "เนื้อหา"; "Scene.Profile.Fields.Placeholder.Label" = "ป้ายชื่อ"; -"Scene.Profile.Header.FollowsYou" = "Follows You"; +"Scene.Profile.Header.FollowsYou" = "ติดตามคุณ"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "ยืนยันเพื่อปิดกั้น %@"; "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "ปิดกั้นบัญชี"; "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "ยืนยันเพื่อซ่อน %@"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/tr.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/tr.lproj/Localizable.strings index b53558d37..814969c39 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/tr.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/tr.lproj/Localizable.strings @@ -222,6 +222,10 @@ yüklenemiyor."; "Scene.HomeTimeline.NavigationBarState.Published" = "Yayınlandı!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Gönderi yayınlanıyor..."; "Scene.HomeTimeline.Title" = "Ana Sayfa"; +"Scene.Notification.FollowRequest.Accept" = "Accept"; +"Scene.Notification.FollowRequest.Accepted" = "Accepted"; +"Scene.Notification.FollowRequest.Reject" = "reject"; +"Scene.Notification.FollowRequest.Rejected" = "Rejected"; "Scene.Notification.Keyobard.ShowEverything" = "Her Şeyi Göster"; "Scene.Notification.Keyobard.ShowMentions" = "Bahsetmeleri Göster"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "gönderini favoriledi"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/vi.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/vi.lproj/Localizable.strings index d54155ca2..b3be7f302 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/vi.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/vi.lproj/Localizable.strings @@ -223,6 +223,10 @@ tải lên Mastodon."; "Scene.HomeTimeline.NavigationBarState.Published" = "Đã đăng!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "Đang đăng tút..."; "Scene.HomeTimeline.Title" = "Bảng tin"; +"Scene.Notification.FollowRequest.Accept" = "Chấp nhận"; +"Scene.Notification.FollowRequest.Accepted" = "Đã chấp nhận"; +"Scene.Notification.FollowRequest.Reject" = "từ chối"; +"Scene.Notification.FollowRequest.Rejected" = "Đã từ chối"; "Scene.Notification.Keyobard.ShowEverything" = "Hiện mọi thứ"; "Scene.Notification.Keyobard.ShowMentions" = "Hiện lượt nhắc"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "thích tút của bạn"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings index e011ce72b..62117499d 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings @@ -223,6 +223,10 @@ "Scene.HomeTimeline.NavigationBarState.Published" = "已发送"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "正在发送..."; "Scene.HomeTimeline.Title" = "主页"; +"Scene.Notification.FollowRequest.Accept" = "接受"; +"Scene.Notification.FollowRequest.Accepted" = "已接受"; +"Scene.Notification.FollowRequest.Reject" = "拒绝"; +"Scene.Notification.FollowRequest.Rejected" = "已拒绝"; "Scene.Notification.Keyobard.ShowEverything" = "显示全部"; "Scene.Notification.Keyobard.ShowMentions" = "显示提及"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "喜欢了你的帖子"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hant.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hant.lproj/Localizable.strings index 470c7d7f4..10fd6837a 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hant.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hant.lproj/Localizable.strings @@ -218,6 +218,10 @@ "Scene.HomeTimeline.NavigationBarState.Published" = "嘟出去!"; "Scene.HomeTimeline.NavigationBarState.Publishing" = "發表嘟文..."; "Scene.HomeTimeline.Title" = "首頁"; +"Scene.Notification.FollowRequest.Accept" = "接受"; +"Scene.Notification.FollowRequest.Accepted" = "已接受"; +"Scene.Notification.FollowRequest.Reject" = "拒絕"; +"Scene.Notification.FollowRequest.Rejected" = "已拒絕"; "Scene.Notification.Keyobard.ShowEverything" = "顯示全部"; "Scene.Notification.Keyobard.ShowMentions" = "顯示提及"; "Scene.Notification.NotificationDescription.FavoritedYourPost" = "最愛了您的嘟文"; diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+FollowRequest.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+FollowRequest.swift index 7adbcdeff..ddde4ffdc 100644 --- a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+FollowRequest.swift +++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Account+FollowRequest.swift @@ -89,3 +89,37 @@ extension Mastodon.API.Account { .eraseToAnyPublisher() } } + +extension Mastodon.API.Account { + + public enum FollowReqeustQuery { + case accept + case reject + } + + public static func followRequest( + session: URLSession, + domain: String, + userID: Mastodon.Entity.Account.ID, + query: FollowReqeustQuery, + authorization: Mastodon.API.OAuth.Authorization + ) -> AnyPublisher, Error> { + switch query { + case .accept: + return acceptFollowRequest( + session: session, + domain: domain, + userID: userID, + authorization: authorization + ) + case .reject: + return rejectFollowRequest( + session: session, + domain: domain, + userID: userID, + authorization: authorization + ) + } // end switch + } + +} diff --git a/MastodonSDK/Sources/MastodonUI/Extension/MetaLabel.swift b/MastodonSDK/Sources/MastodonUI/Extension/MetaLabel.swift index 41fbfe40c..22c05a969 100644 --- a/MastodonSDK/Sources/MastodonUI/Extension/MetaLabel.swift +++ b/MastodonSDK/Sources/MastodonUI/Extension/MetaLabel.swift @@ -118,7 +118,7 @@ extension MetaLabel { case .autoCompletion: font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 22) - textColor = Asset.Colors.brandBlue.color + textColor = Asset.Colors.brand.color case .accountListName: font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .regular), maximumPointSize: 22) @@ -146,7 +146,7 @@ extension MetaLabel { ] linkAttributes = [ .font: font, - .foregroundColor: Asset.Colors.brandBlue.color + .foregroundColor: Asset.Colors.brand.color ] } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView+ViewModel.swift index eec57cb5a..0db2c969f 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView+ViewModel.swift @@ -13,10 +13,13 @@ import MastodonSDK import MastodonAsset import MastodonLocalization import MastodonExtension +import CoreData +import CoreDataStack extension NotificationView { public final class ViewModel: ObservableObject { public var disposeBag = Set() + public var objects = Set() let logger = Logger(subsystem: "NotificationView", category: "ViewModel") @@ -35,11 +38,13 @@ extension NotificationView { @Published public var timestamp: Date? + @Published public var followRequestState = MastodonFollowRequestState(state: .none) + @Published public var transientFollowRequestState = MastodonFollowRequestState(state: .none) + let timestampUpdatePublisher = Timer.publish(every: 1.0, on: .main, in: .common) .autoconnect() .share() .eraseToAnyPublisher() - } } @@ -47,6 +52,7 @@ extension NotificationView.ViewModel { func bind(notificationView: NotificationView) { bindAuthor(notificationView: notificationView) bindAuthorMenu(notificationView: notificationView) + bindFollowRequest(notificationView: notificationView) $userIdentifier .assign(to: \.userIdentifier, on: notificationView.statusView.viewModel) @@ -146,4 +152,54 @@ extension NotificationView.ViewModel { } .store(in: &disposeBag) } + + private func bindFollowRequest(notificationView: NotificationView) { + Publishers.CombineLatest( + $followRequestState, + $transientFollowRequestState + ) + .sink { followRequestState, transientFollowRequestState in + switch followRequestState.state { + case .isAccept: + notificationView.rejectFollowRequestButtonShadowBackgroundContainer.isHidden = true + notificationView.acceptFollowRequestButton.isUserInteractionEnabled = false + notificationView.acceptFollowRequestButton.setImage(nil, for: .normal) + notificationView.acceptFollowRequestButton.setTitle(L10n.Scene.Notification.FollowRequest.accepted, for: .normal) + case .isReject: + notificationView.acceptFollowRequestButtonShadowBackgroundContainer.isHidden = true + notificationView.rejectFollowRequestButton.isUserInteractionEnabled = false + notificationView.rejectFollowRequestButton.setImage(nil, for: .normal) + notificationView.rejectFollowRequestButton.setTitle(L10n.Scene.Notification.FollowRequest.rejected, for: .normal) + default: + break + } + + let state = transientFollowRequestState.state + if state == .isAccepting { + notificationView.acceptFollowRequestActivityIndicatorView.startAnimating() + notificationView.acceptFollowRequestButton.tintColor = .clear + } else { + notificationView.acceptFollowRequestActivityIndicatorView.stopAnimating() + notificationView.acceptFollowRequestButton.tintColor = .white + } + if state == .isRejecting { + notificationView.rejectFollowRequestActivityIndicatorView.startAnimating() + notificationView.rejectFollowRequestButton.tintColor = .clear + } else { + notificationView.rejectFollowRequestActivityIndicatorView.stopAnimating() + notificationView.rejectFollowRequestButton.tintColor = .white + } + + UIView.animate(withDuration: 0.3) { + if state == .isAccept { + notificationView.rejectFollowRequestButtonShadowBackgroundContainer.isHidden = true + } + if state == .isReject { + notificationView.acceptFollowRequestButtonShadowBackgroundContainer.isHidden = true + } + } + } + .store(in: &disposeBag) + } + } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift index 8714c7cd0..daf14b96e 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift @@ -17,6 +17,9 @@ public protocol NotificationViewDelegate: AnyObject { func notificationView(_ notificationView: NotificationView, authorAvatarButtonDidPressed button: AvatarButton) func notificationView(_ notificationView: NotificationView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action) + func notificationView(_ notificationView: NotificationView, acceptFollowRequestButtonDidPressed button: UIButton) + func notificationView(_ notificationView: NotificationView, rejectFollowRequestButtonDidPressed button: UIButton) + func notificationView(_ notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) func notificationView(_ notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) func notificationView(_ notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) @@ -101,6 +104,50 @@ public final class NotificationView: UIView { // notification type indicator imageView public let notificationTypeIndicatorLabel = MetaLabel(style: .notificationTitle) + // follow request + let followRequestAdaptiveMarginContainerView = AdaptiveMarginContainerView() + let followRequestContainerView = UIStackView() + + let acceptFollowRequestButtonShadowBackgroundContainer = ShadowBackgroundContainer() + private(set) lazy var acceptFollowRequestButton: UIButton = { + let button = UIButton() + button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .semibold) + button.setImage(Asset.Editing.checkmark.image.withRenderingMode(.alwaysTemplate), for: .normal) + button.imageView?.contentMode = .scaleAspectFit + button.setBackgroundImage(.placeholder(color: .systemGreen), for: .normal) + button.tintColor = .white + button.layer.masksToBounds = true + button.layer.cornerCurve = .continuous + button.layer.cornerRadius = 4 + button.accessibilityLabel = L10n.Scene.Notification.FollowRequest.accept + acceptFollowRequestButtonShadowBackgroundContainer.cornerRadius = 4 + acceptFollowRequestButtonShadowBackgroundContainer.shadowAlpha = 0.1 + button.addTarget(self, action: #selector(NotificationView.acceptFollowRequestButtonDidPressed(_:)), for: .touchUpInside) + return button + }() + let acceptFollowRequestActivityIndicatorView = UIActivityIndicatorView(style: .medium) + + let rejectFollowRequestButtonShadowBackgroundContainer = ShadowBackgroundContainer() + private(set) lazy var rejectFollowRequestButton: UIButton = { + let button = UIButton() + button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .semibold) + button.setImage(Asset.Editing.xmark.image.withRenderingMode(.alwaysTemplate), for: .normal) + button.imageView?.contentMode = .scaleAspectFit + button.imageEdgeInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2) // tweak xmark size + button.setBackgroundImage(.placeholder(color: .systemRed), for: .normal) + button.tintColor = .white + button.layer.masksToBounds = true + button.layer.cornerCurve = .continuous + button.layer.cornerRadius = 4 + button.accessibilityLabel = L10n.Scene.Notification.FollowRequest.reject + rejectFollowRequestButtonShadowBackgroundContainer.cornerRadius = 4 + rejectFollowRequestButtonShadowBackgroundContainer.shadowAlpha = 0.1 + button.addTarget(self, action: #selector(NotificationView.rejectFollowRequestButtonDidPressed(_:)), for: .touchUpInside) + return button + }() + let rejectFollowRequestActivityIndicatorView = UIActivityIndicatorView(style: .medium) + + // status public let statusView = StatusView() public let quoteStatusViewContainerView = UIView() @@ -110,11 +157,20 @@ public final class NotificationView: UIView { public func prepareForReuse() { disposeBag.removeAll() + viewModel.objects.removeAll() viewModel.authorAvatarImageURL = nil avatarButton.avatarImageView.cancelTask() authorContainerViewBottomPaddingView.isHidden = true + followRequestAdaptiveMarginContainerView.isHidden = true + acceptFollowRequestButtonShadowBackgroundContainer.isHidden = false + rejectFollowRequestButtonShadowBackgroundContainer.isHidden = false + acceptFollowRequestActivityIndicatorView.stopAnimating() + rejectFollowRequestActivityIndicatorView.stopAnimating() + acceptFollowRequestButton.isUserInteractionEnabled = true + rejectFollowRequestButton.isUserInteractionEnabled = true + statusView.isHidden = true statusView.prepareForReuse() @@ -222,6 +278,58 @@ extension NotificationView { ]) authorContainerViewBottomPaddingView.isHidden = true + // follow reqeust + followRequestAdaptiveMarginContainerView.contentView = followRequestContainerView + followRequestAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin + containerStackView.addArrangedSubview(followRequestAdaptiveMarginContainerView) + + acceptFollowRequestButton.translatesAutoresizingMaskIntoConstraints = false + acceptFollowRequestButtonShadowBackgroundContainer.addSubview(acceptFollowRequestButton) + NSLayoutConstraint.activate([ + acceptFollowRequestButton.topAnchor.constraint(equalTo: acceptFollowRequestButtonShadowBackgroundContainer.topAnchor), + acceptFollowRequestButton.leadingAnchor.constraint(equalTo: acceptFollowRequestButtonShadowBackgroundContainer.leadingAnchor), + acceptFollowRequestButton.trailingAnchor.constraint(equalTo: acceptFollowRequestButtonShadowBackgroundContainer.trailingAnchor), + acceptFollowRequestButton.bottomAnchor.constraint(equalTo: acceptFollowRequestButtonShadowBackgroundContainer.bottomAnchor), + ]) + + rejectFollowRequestButton.translatesAutoresizingMaskIntoConstraints = false + rejectFollowRequestButtonShadowBackgroundContainer.addSubview(rejectFollowRequestButton) + NSLayoutConstraint.activate([ + rejectFollowRequestButton.topAnchor.constraint(equalTo: rejectFollowRequestButtonShadowBackgroundContainer.topAnchor), + rejectFollowRequestButton.leadingAnchor.constraint(equalTo: rejectFollowRequestButtonShadowBackgroundContainer.leadingAnchor), + rejectFollowRequestButton.trailingAnchor.constraint(equalTo: rejectFollowRequestButtonShadowBackgroundContainer.trailingAnchor), + rejectFollowRequestButton.bottomAnchor.constraint(equalTo: rejectFollowRequestButtonShadowBackgroundContainer.bottomAnchor), + ]) + + followRequestContainerView.axis = .horizontal + followRequestContainerView.distribution = .fillEqually + followRequestContainerView.spacing = 8 + followRequestContainerView.isLayoutMarginsRelativeArrangement = true + followRequestContainerView.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0) // set bottom padding + followRequestContainerView.addArrangedSubview(acceptFollowRequestButtonShadowBackgroundContainer) + followRequestContainerView.addArrangedSubview(rejectFollowRequestButtonShadowBackgroundContainer) + followRequestAdaptiveMarginContainerView.isHidden = true + + acceptFollowRequestActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false + acceptFollowRequestButton.addSubview(acceptFollowRequestActivityIndicatorView) + NSLayoutConstraint.activate([ + acceptFollowRequestActivityIndicatorView.centerXAnchor.constraint(equalTo: acceptFollowRequestButton.centerXAnchor), + acceptFollowRequestActivityIndicatorView.centerYAnchor.constraint(equalTo: acceptFollowRequestButton.centerYAnchor), + ]) + acceptFollowRequestActivityIndicatorView.color = .white + acceptFollowRequestActivityIndicatorView.hidesWhenStopped = true + acceptFollowRequestActivityIndicatorView.stopAnimating() + + rejectFollowRequestActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false + rejectFollowRequestButton.addSubview(rejectFollowRequestActivityIndicatorView) + NSLayoutConstraint.activate([ + rejectFollowRequestActivityIndicatorView.centerXAnchor.constraint(equalTo: rejectFollowRequestButton.centerXAnchor), + rejectFollowRequestActivityIndicatorView.centerYAnchor.constraint(equalTo: rejectFollowRequestButton.centerYAnchor), + ]) + rejectFollowRequestActivityIndicatorView.color = .white + acceptFollowRequestActivityIndicatorView.hidesWhenStopped = true + rejectFollowRequestActivityIndicatorView.stopAnimating() + // statusView containerStackView.addArrangedSubview(statusView) statusView.setup(style: .notification) @@ -271,10 +379,22 @@ extension NotificationView { } extension NotificationView { + @objc private func avatarButtonDidPressed(_ sender: UIButton) { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") delegate?.notificationView(self, authorAvatarButtonDidPressed: avatarButton) } + + @objc private func acceptFollowRequestButtonDidPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + delegate?.notificationView(self, acceptFollowRequestButtonDidPressed: sender) + } + + @objc private func rejectFollowRequestButtonDidPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + delegate?.notificationView(self, rejectFollowRequestButtonDidPressed: sender) + } + } extension NotificationView { @@ -282,6 +402,10 @@ extension NotificationView { public func setAuthorContainerBottomPaddingViewDisplay() { authorContainerViewBottomPaddingView.isHidden = false } + + public func setFollowRequestAdaptiveMarginContainerViewDisplay() { + followRequestAdaptiveMarginContainerView.isHidden = false + } public func setStatusViewDisplay() { statusView.isHidden = false diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift index e25e5d0a8..7a48ddc3a 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift @@ -26,6 +26,8 @@ extension PollOptionView { var disposeBag = Set() var observations = Set() public var objects = Set() + + let layoutDidUpdate = PassthroughSubject() @Published public var userIdentifier: UserIdentifier? @@ -47,8 +49,8 @@ extension PollOptionView { @Published public var voteState: VoteState = .hidden @Published public var roundedBackgroundViewColor: UIColor = .clear - @Published public var primaryStripProgressViewTintColor: UIColor = Asset.Colors.brandBlue.color - @Published public var secondaryStripProgressViewTintColor: UIColor = Asset.Colors.brandBlue.color.withAlphaComponent(0.5) + @Published public var primaryStripProgressViewTintColor: UIColor = Asset.Colors.brand.color.withAlphaComponent(0.8) + @Published public var secondaryStripProgressViewTintColor: UIColor = Asset.Colors.brand.color.withAlphaComponent(0.5) @Published public var groupedAccessibilityLabel = "" @@ -180,6 +182,39 @@ extension PollOptionView.ViewModel { } .store(in: &disposeBag) + Publishers.CombineLatest( + $voteState, + layoutDidUpdate + ) + .sink { voteState, _ in + guard case .plain = view.style else { return } + + view.layoutIfNeeded() + + switch voteState { + case .hidden: + view.optionTextField.textColor = Asset.Colors.Label.primary.color + view.optionTextField.layer.removeShadow() + case .reveal(_, let percentage, _): + if CGFloat(percentage) * view.roundedBackgroundView.frame.width > view.optionLabelMiddlePaddingView.frame.minX { + view.optionTextField.textColor = .white + view.optionTextField.layer.setupShadow(x: 0, y: 0, blur: 4, spread: 0) + } else { + view.optionTextField.textColor = Asset.Colors.Label.primary.color + view.optionTextField.layer.removeShadow() + } + + if CGFloat(percentage) * view.roundedBackgroundView.frame.width > view.optionLabelMiddlePaddingView.frame.maxX { + view.optionPercentageLabel.textColor = .white + view.optionPercentageLabel.layer.setupShadow(x: 0, y: 0, blur: 4, spread: 0) + } else { + view.optionPercentageLabel.textColor = Asset.Colors.Label.primary.color + view.optionPercentageLabel.layer.removeShadow() + } + } + } + .store(in: &disposeBag) + bindAccessibility(view: view) } @@ -196,4 +231,3 @@ extension PollOptionView.ViewModel { .store(in: &disposeBag) } } - diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift index df000233c..04a032563 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift @@ -32,7 +32,7 @@ public final class PollOptionView: UIView { public let roundedBackgroundView = UIView() public let voteProgressStripView: StripProgressView = { let view = StripProgressView() - view.tintColor = Asset.Colors.brandBlue.color + view.tintColor = Asset.Colors.brand.color return view }() @@ -45,7 +45,7 @@ public final class PollOptionView: UIView { let imageView = UIImageView() let image = UIImage(systemName: "checkmark", withConfiguration: UIImage.SymbolConfiguration(pointSize: 14, weight: .bold))! imageView.image = image.withRenderingMode(.alwaysTemplate) - imageView.tintColor = Asset.Colors.brandBlue.color + imageView.tintColor = Asset.Colors.brand.color return imageView }() @@ -53,7 +53,7 @@ public final class PollOptionView: UIView { let imageView = UIImageView() let image = Asset.Circles.plusCircle.image imageView.image = image.withRenderingMode(.alwaysTemplate) - imageView.tintColor = Asset.Colors.brandBlue.color + imageView.tintColor = Asset.Colors.brand.color return imageView }() @@ -203,44 +203,13 @@ extension PollOptionView { super.layoutSubviews() updateCornerRadius() + viewModel.layoutDidUpdate.send() } public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) - if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { - -// func updateTextAppearance() { -// // guard let voteState = attribute?.voteState else { -// // pollOptionView.optionTextField.textColor = Asset.Colors.Label.primary.color -// // pollOptionView.optionTextField.layer.removeShadow() -// // return -// // } -// // -// // switch voteState { -// // case .hidden: -// // pollOptionView.optionTextField.textColor = Asset.Colors.Label.primary.color -// // pollOptionView.optionTextField.layer.removeShadow() -// // case .reveal(_, let percentage, _): -// // if CGFloat(percentage) * pollOptionView.voteProgressStripView.frame.width > pollOptionView.optionLabelMiddlePaddingView.frame.minX { -// // pollOptionView.optionTextField.textColor = .white -// // pollOptionView.optionTextField.layer.setupShadow(x: 0, y: 0, blur: 4, spread: 0) -// // } else { -// // pollOptionView.optionTextField.textColor = Asset.Colors.Label.primary.color -// // pollOptionView.optionTextField.layer.removeShadow() -// // } -// // -// // if CGFloat(percentage) * pollOptionView.voteProgressStripView.frame.width > pollOptionView.optionLabelMiddlePaddingView.frame.maxX { -// // pollOptionView.optionPercentageLabel.textColor = .white -// // pollOptionView.optionPercentageLabel.layer.setupShadow(x: 0, y: 0, blur: 4, spread: 0) -// // } else { -// // pollOptionView.optionPercentageLabel.textColor = Asset.Colors.Label.primary.color -// // pollOptionView.optionPercentageLabel.layer.removeShadow() -// // } -// // } -// } - - } + viewModel.layoutDidUpdate.send() } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift index 0572cc0f6..b93d44b73 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/ProfileCardView.swift @@ -78,7 +78,7 @@ public final class ProfileCardView: UIView { ] metaText.linkAttributes = [ .font: UIFont.preferredFont(forTextStyle: .body), - .foregroundColor: Asset.Colors.brandBlue.color, + .foregroundColor: Asset.Colors.brand.color, ] return metaText }() diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift index bdcbd473e..4c983df34 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift @@ -147,8 +147,8 @@ public final class StatusView: UIView { .foregroundColor: Asset.Colors.Label.primary.color, ] metaText.linkAttributes = [ - .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)), - .foregroundColor: Asset.Colors.brandBlue.color, + .font: UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)), + .foregroundColor: Asset.Colors.brand.color, ] return metaText }() @@ -203,8 +203,8 @@ public final class StatusView: UIView { let button = HitTestExpandedButton() button.titleLabel?.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 14, weight: .semibold)) button.setTitle(L10n.Common.Controls.Status.Poll.vote, for: .normal) - button.setTitleColor(Asset.Colors.brandBlue.color, for: .normal) - button.setTitleColor(Asset.Colors.brandBlue.color.withAlphaComponent(0.8), for: .highlighted) + button.setTitleColor(Asset.Colors.brand.color, for: .normal) + button.setTitleColor(Asset.Colors.brand.color.withAlphaComponent(0.8), for: .highlighted) button.setTitleColor(Asset.Colors.Button.disabled.color, for: .disabled) button.isEnabled = false return button diff --git a/MastodonSDK/Sources/MastodonUI/View/Control/LineChartView.swift b/MastodonSDK/Sources/MastodonUI/View/Control/LineChartView.swift index c90b59f0e..833ee76a5 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Control/LineChartView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Control/LineChartView.swift @@ -40,8 +40,8 @@ extension LineChartView { layer.addSublayer(gradientLayer) gradientLayer.colors = [ - Asset.Colors.brandBlue.color.withAlphaComponent(0.5).cgColor, // set the same alpha to fill - Asset.Colors.brandBlue.color.withAlphaComponent(0.5).cgColor, + Asset.Colors.Primary._300.color.withAlphaComponent(0.5).cgColor, // set the same alpha to fill + Asset.Colors.Primary._300.color.withAlphaComponent(0.5).cgColor, ] gradientLayer.startPoint = CGPoint(x: 0.5, y: 0) gradientLayer.endPoint = CGPoint(x: 0.5, y: 1) @@ -91,7 +91,7 @@ extension LineChartView { } lineShapeLayer.lineWidth = 1 - lineShapeLayer.strokeColor = Asset.Colors.brandBlue.color.cgColor + lineShapeLayer.strokeColor = Asset.Colors.Primary._700.color.cgColor lineShapeLayer.fillColor = UIColor.clear.cgColor lineShapeLayer.lineJoin = .round lineShapeLayer.lineCap = .round @@ -103,7 +103,7 @@ extension LineChartView { maskPath.close() let maskLayer = CAShapeLayer() maskLayer.path = maskPath.cgPath - maskLayer.fillColor = Asset.Colors.brandBlue.color.cgColor + maskLayer.fillColor = Asset.Colors.brand.color.cgColor maskLayer.strokeColor = UIColor.clear.cgColor maskLayer.lineWidth = 0.0 gradientLayer.mask = maskLayer diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 3d06762c8..21baf4a3e 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleVersion - 140 + 144 diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 3d06762c8..21baf4a3e 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -15,8 +15,8 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleVersion - 140 + 144 diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index a2e1ea1c2..1361dc875 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleVersion - 140 + 144 NSExtension NSExtensionPointIdentifier diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 599d44f9f..18b7be8a4 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.4.4 + 1.4.5 CFBundleVersion - 140 + 144 NSExtension NSExtensionAttributes diff --git a/ShareActionExtension/Scene/ShareViewController.swift b/ShareActionExtension/Scene/ShareViewController.swift index 622e0106b..542fce6d5 100644 --- a/ShareActionExtension/Scene/ShareViewController.swift +++ b/ShareActionExtension/Scene/ShareViewController.swift @@ -25,8 +25,8 @@ class ShareViewController: UIViewController { let button = RoundedEdgesButton(type: .custom) button.setTitle(L10n.Scene.Compose.composeAction, for: .normal) button.titleLabel?.font = .systemFont(ofSize: 14, weight: .bold) - button.setBackgroundImage(.placeholder(color: Asset.Colors.brandBlue.color), for: .normal) - button.setBackgroundImage(.placeholder(color: Asset.Colors.brandBlue.color.withAlphaComponent(0.5)), for: .highlighted) + button.setBackgroundImage(.placeholder(color: Asset.Colors.brand.color), for: .normal) + button.setBackgroundImage(.placeholder(color: Asset.Colors.brand.color.withAlphaComponent(0.5)), for: .highlighted) button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.disabled.color), for: .disabled) button.setTitleColor(.white, for: .normal) button.contentEdgeInsets = UIEdgeInsets(top: 6, left: 16, bottom: 5, right: 16) // set 28pt height