Skip to content

Commit 8752b5e

Browse files
fix(cat-voices): sharing proposals url (#2749)
* refactor: Sharing resources url + fix sharing encoded url * refactor: simplify code
1 parent be32a04 commit 8752b5e

File tree

28 files changed

+454
-256
lines changed

28 files changed

+454
-256
lines changed

catalyst_voices/apps/voices/lib/app/view/app_content.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:catalyst_voices/app/view/app_session_listener.dart';
66
import 'package:catalyst_voices/app/view/app_splash_screen_manager.dart';
77
import 'package:catalyst_voices/app/view/video_cache/app_video_precache.dart';
88
import 'package:catalyst_voices/common/ext/preferences_ext.dart';
9+
import 'package:catalyst_voices/share/share_manager.dart';
910
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
1011
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
1112
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
@@ -64,9 +65,7 @@ final class _AppContent extends StatelessWidget {
6465
routerConfig: routerConfig,
6566
themeMode: themeMode,
6667
theme: ThemeBuilder.buildTheme(),
67-
darkTheme: ThemeBuilder.buildTheme(
68-
brightness: Brightness.dark,
69-
),
68+
darkTheme: ThemeBuilder.buildTheme(brightness: Brightness.dark),
7069
debugShowCheckedModeBanner: false,
7170
builder: (_, child) {
7271
return AppGlobalShortcuts(
@@ -81,7 +80,9 @@ final class _AppContent extends StatelessWidget {
8180
// screen behavior.
8281
child: AppSplashScreenManager(
8382
child: AppMobileAccessRestriction(
84-
child: child ?? const SizedBox.shrink(),
83+
child: DefaultShareManager(
84+
child: child ?? const SizedBox.shrink(),
85+
),
8586
),
8687
),
8788
),

catalyst_voices/apps/voices/lib/common/constants/constants.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import 'package:catalyst_cardano_serialization/catalyst_cardano_serialization.dart';
2-
import 'package:catalyst_voices/dependency/dependencies.dart';
3-
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
42

53
abstract class VoicesConstants {
64
static const _docs = 'https://docs.projectcatalyst.io';
@@ -40,10 +38,6 @@ abstract class VoicesConstants {
4038
static const confirmSeedPhraseUrl = '$_catalystApp/getting-started#confirm-seed-phrase';
4139
static const campaignTimeline = '$_docs/current-fund/fund-basics/fund-timeline';
4240

43-
static String becomeReviewerUrl() {
44-
return '${Dependencies.instance.get<AppEnvironment>().type.reviews}/register';
45-
}
46-
4741
static String cardanoScanStakeAddressUrl(ShelleyAddress stakeAddress) {
4842
switch (stakeAddress.network) {
4943
case NetworkId.mainnet:

catalyst_voices/apps/voices/lib/dependency/dependencies.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import 'dart:async';
33
import 'package:catalyst_cardano/catalyst_cardano.dart';
44
import 'package:catalyst_key_derivation/catalyst_key_derivation.dart';
55
import 'package:catalyst_voices/app/view/video_cache/app_video_manager.dart';
6+
import 'package:catalyst_voices/share/resource_url_resolver.dart';
7+
import 'package:catalyst_voices/share/share_manager.dart';
68
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
79
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
810
import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
@@ -355,6 +357,15 @@ final class Dependencies extends DependencyProvider {
355357
get<AppConfig>(),
356358
);
357359
});
360+
registerLazySingleton<ResourceUrlResolver>(() {
361+
return ResourceUrlResolver(environment: get<AppEnvironment>());
362+
});
363+
registerLazySingleton<ShareService>(() {
364+
return ShareService(
365+
get<ResourceUrlResolver>(),
366+
get<ResourceUrlResolver>(),
367+
);
368+
});
358369
}
359370

360371
void _registerStorages() {
@@ -417,5 +428,6 @@ final class Dependencies extends DependencyProvider {
417428
},
418429
dispose: (manager) => manager.dispose(),
419430
);
431+
registerLazySingleton<ShareManager>(() => DelegatingShareManager(get<ShareService>()));
420432
}
421433
}

catalyst_voices/apps/voices/lib/pages/discovery/sections/stay_involved.dart

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:async';
33
import 'package:catalyst_voices/common/constants/constants.dart';
44
import 'package:catalyst_voices/common/ext/build_context_ext.dart';
55
import 'package:catalyst_voices/pages/discovery/sections/session_account_catalyst_id.dart';
6+
import 'package:catalyst_voices/share/share_manager.dart';
67
import 'package:catalyst_voices/widgets/text/campaign_stage_time_text.dart';
78
import 'package:catalyst_voices/widgets/widgets.dart';
89
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
@@ -11,6 +12,7 @@ import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
1112
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
1213
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
1314
import 'package:flutter/material.dart';
15+
import 'package:url_launcher/url_launcher.dart';
1416

1517
class StayInvolved extends StatelessWidget {
1618
const StayInvolved({super.key});
@@ -55,7 +57,9 @@ class _CopyCatalystIdTipText extends StatelessWidget {
5557
child: Padding(
5658
padding: const EdgeInsets.only(top: 20),
5759
child: TipText(
58-
context.l10n.tipCopyCatalystIdForReviewTool(VoicesConstants.becomeReviewerUrl()),
60+
context.l10n.tipCopyCatalystIdForReviewTool(
61+
ShareManager.of(context).becomeReviewer().decoded(),
62+
),
5963
style:
6064
context.textTheme.bodyMedium?.copyWith(color: context.colors.textOnPrimaryLevel1),
6165
),
@@ -177,7 +181,11 @@ class _ReviewerCard extends StatelessWidget {
177181
),
178182
_StayInvolvedActionButton(
179183
title: context.l10n.becomeReviewer,
180-
urlString: VoicesConstants.becomeReviewerUrl(),
184+
onTap: () {
185+
final shareManager = ShareManager.of(context);
186+
final uri = shareManager.becomeReviewer();
187+
unawaited(launchUrl(uri));
188+
},
181189
trailing: VoicesAssets.icons.externalLink.buildIcon(),
182190
),
183191
],
@@ -188,31 +196,26 @@ class _ReviewerCard extends StatelessWidget {
188196

189197
class _StayInvolvedActionButton extends StatelessWidget with LaunchUrlMixin {
190198
final String title;
191-
final String urlString;
192199
final Widget? trailing;
200+
final VoidCallback? onTap;
193201

194202
const _StayInvolvedActionButton({
195203
required this.title,
196-
required this.urlString,
197204
this.trailing,
205+
this.onTap,
198206
});
199207

200208
@override
201209
Widget build(BuildContext context) {
202210
return Padding(
203211
padding: const EdgeInsets.only(top: 20),
204212
child: VoicesFilledButton(
205-
onTap: _handleUrlTap,
213+
onTap: onTap,
206214
trailing: trailing,
207215
child: Text(title),
208216
),
209217
);
210218
}
211-
212-
Future<void> _handleUrlTap() async {
213-
final url = urlString.getUri();
214-
await launchUri(url);
215-
}
216219
}
217220

218221
class _StayInvolvedCard extends StatelessWidget {
@@ -327,7 +330,10 @@ class _VoterCard extends StatelessWidget {
327330
),
328331
_StayInvolvedActionButton(
329332
title: context.l10n.becomeVoter,
330-
urlString: VoicesConstants.afterSubmissionUrl,
333+
onTap: () {
334+
final uri = Uri.parse(VoicesConstants.afterSubmissionUrl);
335+
unawaited(launchUrl(uri));
336+
},
331337
),
332338
],
333339
),

catalyst_voices/apps/voices/lib/pages/proposal/widget/proposal_share_button.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'dart:async';
22

3-
import 'package:catalyst_voices/routes/routing/proposal_route.dart';
43
import 'package:catalyst_voices/widgets/buttons/voices_buttons.dart';
54
import 'package:catalyst_voices/widgets/modals/proposals/share_proposal_dialog.dart';
65
import 'package:catalyst_voices/widgets/snackbar/voices_snackbar.dart';
@@ -23,8 +22,7 @@ class ProposalShareButton extends StatelessWidget {
2322
return ShareButton(
2423
onTap: () {
2524
if (proposalRef != null) {
26-
final url = ProposalRoute.fromRef(ref: proposalRef).location;
27-
unawaited(ShareProposalDialog.show(context, url));
25+
unawaited(ShareProposalDialog.show(context, ref: proposalRef));
2826
} else {
2927
_showErrorSnackbar(context);
3028
}

catalyst_voices/apps/voices/lib/pages/spaces/drawer/opportunities_drawer.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:catalyst_voices/common/constants/constants.dart';
22
import 'package:catalyst_voices/common/ext/build_context_ext.dart';
33
import 'package:catalyst_voices/pages/spaces/drawer/session_account_drawer_catalyst_id.dart';
4+
import 'package:catalyst_voices/share/share_manager.dart';
45
import 'package:catalyst_voices/widgets/widgets.dart';
56
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
67
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
@@ -70,7 +71,7 @@ class _BecomeReviewerCard extends StatelessWidget with LaunchUrlMixin {
7071
const SizedBox(height: 20),
7172
_OpportunityActionButton(
7273
onTap: () async {
73-
await launchUri(VoicesConstants.becomeReviewerUrl().getUri());
74+
await launchUri(ShareManager.of(context).becomeReviewer());
7475
},
7576
title: context.l10n.becomeReviewer,
7677
trailing: VoicesAssets.icons.externalLink.buildIcon(),
@@ -86,8 +87,10 @@ class _CopyCatalystIdTipText extends StatelessWidget {
8687

8788
@override
8889
Widget build(BuildContext context) {
90+
final url = ShareManager.of(context).becomeReviewer().decoded();
91+
8992
return TipText(
90-
context.l10n.tipCopyCatalystIdForReviewTool(VoicesConstants.becomeReviewerUrl()),
93+
context.l10n.tipCopyCatalystIdForReviewTool(url),
9194
style: context.textTheme.bodyMedium?.copyWith(color: context.colors.textOnPrimaryLevel1),
9295
);
9396
}

catalyst_voices/apps/voices/lib/pages/workspace/proposal_menu_action_button.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,7 @@ class _ProposalMenuActionButtonState extends State<ProposalMenuActionButton> {
183183
}
184184

185185
void _shareProposal() {
186-
final url = ProposalRoute.fromRef(ref: widget.ref).location;
187-
unawaited(ShareProposalDialog.show(context, url));
186+
unawaited(ShareProposalDialog.show(context, ref: widget.ref));
188187
}
189188

190189
void _showLatestLocalProposalWarningSnackbar() {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'package:catalyst_voices/routes/routes.dart';
2+
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
3+
import 'package:catalyst_voices_services/catalyst_voices_services.dart';
4+
5+
final class ResourceUrlResolver
6+
implements ShareAppResourceUrlResolver, ShareReviewsResourceUrlResolver {
7+
final AppEnvironment environment;
8+
9+
const ResourceUrlResolver({
10+
required this.environment,
11+
});
12+
13+
@override
14+
Uri becomeReviewer() {
15+
return environment.type.reviews.replace(path: 'register');
16+
}
17+
18+
@override
19+
Uri proposal({required DocumentRef ref}) {
20+
final app = environment.type.app;
21+
final location = ProposalRoute.fromRef(ref: ref).location;
22+
23+
return app.resolve(location);
24+
}
25+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import 'package:catalyst_voices/dependency/dependencies.dart';
2+
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
3+
import 'package:catalyst_voices_services/catalyst_voices_services.dart';
4+
import 'package:flutter/widgets.dart';
5+
6+
class DefaultShareManager extends StatelessWidget {
7+
final Widget child;
8+
9+
const DefaultShareManager({
10+
super.key,
11+
required this.child,
12+
});
13+
14+
@override
15+
Widget build(BuildContext context) {
16+
return _ShareManagerScope(
17+
manager: Dependencies.instance.get<ShareManager>(),
18+
child: child,
19+
);
20+
}
21+
}
22+
23+
final class DelegatingShareManager implements ShareManager {
24+
final ShareService delegate;
25+
26+
const DelegatingShareManager(this.delegate);
27+
28+
@override
29+
Uri becomeReviewer() => delegate.becomeReviewer();
30+
31+
@override
32+
Uri resolveProposalUrl({required DocumentRef ref}) => delegate.resolveProposalUrl(ref: ref);
33+
34+
@override
35+
Future<void> share(ShareData data, {required ShareChannel channel}) {
36+
return delegate.share(data, channel: channel);
37+
}
38+
}
39+
40+
abstract interface class ShareManager implements ShareService {
41+
const factory ShareManager(ShareService delegate) = DelegatingShareManager;
42+
43+
static ShareManager? maybeOf(BuildContext context) {
44+
return context.dependOnInheritedWidgetOfExactType<_ShareManagerScope>()?._shareManager;
45+
}
46+
47+
static ShareManager of(BuildContext context) {
48+
final manager = maybeOf(context);
49+
assert(
50+
manager != null,
51+
'Default ShareManger was not found. '
52+
'Make sure to add DelegatingShareManager in widget tree',
53+
);
54+
return manager!;
55+
}
56+
}
57+
58+
class _ShareManagerScope extends InheritedWidget {
59+
final ShareManager _shareManager;
60+
61+
const _ShareManagerScope({
62+
required ShareManager manager,
63+
required super.child,
64+
}) : _shareManager = manager;
65+
66+
@override
67+
bool updateShouldNotify(covariant _ShareManagerScope oldWidget) {
68+
return _shareManager != oldWidget._shareManager;
69+
}
70+
}

catalyst_voices/apps/voices/lib/widgets/cards/proposal/pending_proposal_card.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'package:catalyst_voices/common/ext/build_context_ext.dart';
22
import 'package:catalyst_voices/common/formatters/date_formatter.dart';
3-
import 'package:catalyst_voices/routes/routes.dart';
43
import 'package:catalyst_voices/widgets/cards/proposal/proposal_border.dart';
54
import 'package:catalyst_voices/widgets/modals/proposals/share_proposal_dialog.dart';
65
import 'package:catalyst_voices/widgets/text/day_month_time_text.dart';
@@ -352,8 +351,7 @@ class _Topbar extends StatelessWidget {
352351
key: const Key('ShareBtn'),
353352
circle: false,
354353
onTap: () async {
355-
final url = ProposalRoute.fromRef(ref: proposalRef).location;
356-
await ShareProposalDialog.show(context, url);
354+
await ShareProposalDialog.show(context, ref: proposalRef);
357355
},
358356
),
359357
if (onFavoriteChanged != null) ...[

0 commit comments

Comments
 (0)