From d90504eed96a467ab8e2c11c1cb06e565b946c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20W=C3=B3jcik?= Date: Tue, 21 Jul 2026 08:20:43 +0200 Subject: [PATCH] BTHLABS-94: Pass `is_netloc_banned` from save to share extension --- .../Base.lproj/MainInterface.storyboard | 41 ++++++++++--------- .../ShareViewController.h | 1 + .../ShareViewController.m | 15 +++++++ .../Base.lproj/ShareViewController.xib | 19 +++++---- .../ShareViewController.h | 1 + .../ShareViewController.m | 19 +++++++++ .../hotpocket_backend/apps/ui/dto/rpc.py | 2 + .../apps/ui/rpc_methods/saves.py | 1 + .../ui/services/workflows/saves/create.py | 14 +++++-- services/backend/setup.cfg | 4 +- .../tests/ui/views/rpc/saves/test_create.py | 3 ++ .../assets/_locales/en/messages.json | 4 ++ services/extension/src/content/main.js | 7 +++- .../popup_content_netloc_banned.html | 14 +++++++ .../soa/hotpocket_soa/dto/associations.py | 13 ++++++ 15 files changed, 124 insertions(+), 34 deletions(-) create mode 100644 services/extension/src/content/templates/popup_content_netloc_banned.html diff --git a/services/apple/iOS (Share Extension)/Base.lproj/MainInterface.storyboard b/services/apple/iOS (Share Extension)/Base.lproj/MainInterface.storyboard index fa64a4d..f30abdc 100644 --- a/services/apple/iOS (Share Extension)/Base.lproj/MainInterface.storyboard +++ b/services/apple/iOS (Share Extension)/Base.lproj/MainInterface.storyboard @@ -1,8 +1,8 @@ - + - + @@ -44,8 +44,8 @@ - + @@ -94,7 +94,7 @@ Gw - + @@ -102,6 +102,9 @@ Gw + + + @@ -118,7 +121,7 @@ Gw - + @@ -183,7 +186,7 @@ Gw - + @@ -211,7 +214,7 @@ Gw - + diff --git a/services/apple/macOS (Share Extension)/ShareViewController.h b/services/apple/macOS (Share Extension)/ShareViewController.h index b48f0fe..0e7f682 100644 --- a/services/apple/macOS (Share Extension)/ShareViewController.h +++ b/services/apple/macOS (Share Extension)/ShareViewController.h @@ -18,6 +18,7 @@ @property BOOL errorViewHidden; @property BOOL unprocessableEntityViewHidden; @property NSString *uname; +@property NSString *savedLabelText; @property IBOutlet NSProgressIndicator *progressIndicator; diff --git a/services/apple/macOS (Share Extension)/ShareViewController.m b/services/apple/macOS (Share Extension)/ShareViewController.m index ec2d26e..2b5090b 100644 --- a/services/apple/macOS (Share Extension)/ShareViewController.m +++ b/services/apple/macOS (Share Extension)/ShareViewController.m @@ -29,6 +29,21 @@ #endif self.errorViewHidden = NO; } else { + self.savedLabelText = NSLocalizedString( + @"Your link has been saved!", + @"Your link has been saved!" + ); + + NSDictionary *save = result.result; + + BOOL isNetlocBanned = [(NSNumber *)[save valueForKey:@"is_netloc_banned"] boolValue]; + if (isNetlocBanned == YES) { + self.savedLabelText = NSLocalizedString( + @"Your link has been saved, but you may want to update its title.", + @"Your link has been saved, but you may want to update its title." + ); + } + self.doneViewHidden = NO; } }); @@ -71,6 +86,10 @@ self.unprocessableEntityViewHidden = YES; self.uname = [NSBundle uname]; + self.savedLabelText = NSLocalizedString( + @"Your link has been saved!", + @"Your link has been saved!" + ); self.api = [[HPAPI alloc] init]; if (self.api.rpcClient.hasCredentials == YES) { diff --git a/services/backend/hotpocket_backend/apps/ui/dto/rpc.py b/services/backend/hotpocket_backend/apps/ui/dto/rpc.py index a5d59d5..0ed12b8 100644 --- a/services/backend/hotpocket_backend/apps/ui/dto/rpc.py +++ b/services/backend/hotpocket_backend/apps/ui/dto/rpc.py @@ -10,10 +10,12 @@ class SavesCreateOut(pydantic.BaseModel): id: uuid.UUID target_uuid: uuid.UUID url: pydantic.AnyHttpUrl + is_netloc_banned: bool def to_rpc(self) -> dict: return { 'id': self.id, 'target_uuid': self.target_uuid, 'url': str(self.url), + 'is_netloc_banned': self.is_netloc_banned, } diff --git a/services/backend/hotpocket_backend/apps/ui/rpc_methods/saves.py b/services/backend/hotpocket_backend/apps/ui/rpc_methods/saves.py index f61d8c0..ab40dac 100644 --- a/services/backend/hotpocket_backend/apps/ui/rpc_methods/saves.py +++ b/services/backend/hotpocket_backend/apps/ui/rpc_methods/saves.py @@ -25,6 +25,7 @@ def create(request: HttpRequest, url: str) -> SavesCreateOut: 'url': request.build_absolute_uri(reverse( 'ui.associations.view', args=(association.pk,), )), + 'is_netloc_banned': association.target.is_netloc_banned, }) return result diff --git a/services/backend/hotpocket_backend/apps/ui/services/workflows/saves/create.py b/services/backend/hotpocket_backend/apps/ui/services/workflows/saves/create.py index b19fe3b..8b7e9b6 100644 --- a/services/backend/hotpocket_backend/apps/ui/services/workflows/saves/create.py +++ b/services/backend/hotpocket_backend/apps/ui/services/workflows/saves/create.py @@ -9,7 +9,10 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from hotpocket_backend.apps.accounts.types import PAccount -from hotpocket_soa.dto.associations import AssociationOut +from hotpocket_soa.dto.associations import ( + AssociationOut, + AssociationWithTargetOut, +) from hotpocket_soa.dto.celery import AsyncResultOut from hotpocket_soa.dto.saves import SaveIn, SaveOut @@ -69,9 +72,14 @@ class CreateSaveWorkflow(SaveWorkflow): request: HttpRequest, account: PAccount, url: str, - ) -> AssociationOut: + ) -> AssociationWithTargetOut: save, association, processing_result = self.create_associate_and_process( account, url, ) - return association + result = AssociationWithTargetOut.from_association_save( + association=association, + save=save, + ) + + return result diff --git a/services/backend/setup.cfg b/services/backend/setup.cfg index 388b2b9..d00c218 100644 --- a/services/backend/setup.cfg +++ b/services/backend/setup.cfg @@ -22,10 +22,10 @@ line_length=80 use_parentheses=true combine_as_imports=true star_first=true -extend_skip_glob=hotpocket_backend/apps/*/migrations/*.py +extend_skip_glob=hotpocket_backend/apps/*/migrations/*.py,hotpocket_backend/playground.py [mypy] -exclude = (apps/.+?/migrations/.+)|(ops/docker/.+)|(ops/metal/.+)|(testing/.+) +exclude = (apps/.+?/migrations/.+)|(ops/docker/.+)|(ops/metal/.+)|(testing/.+)|(playground.py) [mypy-celery.*] ignore_missing_imports = true diff --git a/services/backend/tests/ui/views/rpc/saves/test_create.py b/services/backend/tests/ui/views/rpc/saves/test_create.py index 2688f21..512f365 100644 --- a/services/backend/tests/ui/views/rpc/saves/test_create.py +++ b/services/backend/tests/ui/views/rpc/saves/test_create.py @@ -60,6 +60,7 @@ def test_ok(authenticated_client: Client, assert call_result['result']['url'].endswith(reverse( 'ui.associations.view', args=(association_pk,), )) + assert call_result['result']['is_netloc_banned'] is False AssociationsTestingService().assert_created( pk=association_pk, @@ -105,6 +106,8 @@ def test_ok_netloc_banned(authenticated_client: Client, save_pk = uuid.UUID(call_result['result']['target_uuid']) + assert call_result['result']['is_netloc_banned'] is True + SavesTestingService().assert_created( pk=save_pk, account_uuid=account.pk, diff --git a/services/extension/assets/_locales/en/messages.json b/services/extension/assets/_locales/en/messages.json index eb4cc31..bbaa14c 100644 --- a/services/extension/assets/_locales/en/messages.json +++ b/services/extension/assets/_locales/en/messages.json @@ -23,6 +23,10 @@ "message": "Your link has been saved!", "description": "Message of the success content popup." }, + "content_popup_content_netloc_banned_message": { + "message": "Your link has been saved, but you may want to update its title.", + "description": "Message of the success content popup." + }, "content_popup_content_error_title": { "message": "Oops!", "description": "Title of the error content popup." diff --git a/services/extension/src/content/main.js b/services/extension/src/content/main.js index 3c3d6c9..f0aac78 100644 --- a/services/extension/src/content/main.js +++ b/services/extension/src/content/main.js @@ -3,6 +3,7 @@ import HotPocketExtension from '../common'; import POPUP from './templates/popup.html'; import POPUP_CONTENT_SAVING from './templates/popup_content_saving.html'; import POPUP_CONTENT_SUCCESS from './templates/popup_content_success.html'; +import POPUP_CONTENT_NETLOC_BANNED from './templates/popup_content_netloc_banned.html'; import POPUP_CONTENT_ERROR from './templates/popup_content_error.html'; class Popup { @@ -93,16 +94,20 @@ const doHandleBrowserActionClickedMessage = (message) => { }; const doHandleSaveMessage = (message) => { + const save = (message.result || {}); + let content = POPUP_CONTENT_SUCCESS; if (message.result === null) { content = POPUP_CONTENT_ERROR; + } else if (save.is_netloc_banned === true) { + content = POPUP_CONTENT_NETLOC_BANNED; } if (currentPopup === null) { currentPopup = new Popup(); currentPopup.show(content); } else { - currentPopup.update(content, (message.result || {}).url); + currentPopup.update(content, save.url); } }; diff --git a/services/extension/src/content/templates/popup_content_netloc_banned.html b/services/extension/src/content/templates/popup_content_netloc_banned.html new file mode 100644 index 0000000..023eda4 --- /dev/null +++ b/services/extension/src/content/templates/popup_content_netloc_banned.html @@ -0,0 +1,14 @@ +

+ +
+ +
+ + +

diff --git a/services/packages/soa/hotpocket_soa/dto/associations.py b/services/packages/soa/hotpocket_soa/dto/associations.py index c94fe2c..9075e8f 100644 --- a/services/packages/soa/hotpocket_soa/dto/associations.py +++ b/services/packages/soa/hotpocket_soa/dto/associations.py @@ -2,6 +2,7 @@ from __future__ import annotations import datetime +import typing import uuid import pydantic @@ -50,6 +51,18 @@ class AssociationOut(ModelOut): class AssociationWithTargetOut(AssociationOut): target: SaveOut + @classmethod + def from_association_save(cls: typing.Type[typing.Self], + association: AssociationOut, + save: SaveOut, + ) -> typing.Self: + return cls.model_validate( + obj={ + **association.model_dump(by_alias=True), + 'target': save, + }, + ) + @property def title(self) -> str | None: return self.get_title() or self.target.title