Add option to claim a custom referral code (#2794)
This commit is contained in:
@@ -15,6 +15,15 @@ class StorageBonusGateway {
|
||||
return _enteDio.post("/storage-bonus/referral-claim?code=$code");
|
||||
}
|
||||
|
||||
Future<void> updateCode(String code) {
|
||||
return _enteDio.post(
|
||||
"/storage-bonus/change-code?code=$code",
|
||||
data: {
|
||||
"code": code,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<BonusDetails> getBonusDetails() async {
|
||||
final response = await _enteDio.get("/storage-bonus/details");
|
||||
return BonusDetails.fromJson(response.data);
|
||||
|
||||
9
mobile/lib/generated/intl/messages_en.dart
generated
9
mobile/lib/generated/intl/messages_en.dart
generated
@@ -415,6 +415,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"castInstruction": MessageLookupByLibrary.simpleMessage(
|
||||
"Visit cast.ente.io on the device you want to pair.\n\nEnter the code below to play the album on your TV."),
|
||||
"centerPoint": MessageLookupByLibrary.simpleMessage("Center point"),
|
||||
"change": MessageLookupByLibrary.simpleMessage("Change"),
|
||||
"changeEmail": MessageLookupByLibrary.simpleMessage("Change email"),
|
||||
"changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage(
|
||||
"Change location of selected items?"),
|
||||
@@ -424,6 +425,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Change password"),
|
||||
"changePermissions":
|
||||
MessageLookupByLibrary.simpleMessage("Change permissions?"),
|
||||
"changeYourReferralCode":
|
||||
MessageLookupByLibrary.simpleMessage("Change your referral code"),
|
||||
"checkForUpdates":
|
||||
MessageLookupByLibrary.simpleMessage("Check for updates"),
|
||||
"checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -433,7 +436,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"cl_guest_view_call_to_action": MessageLookupByLibrary.simpleMessage(
|
||||
"Select photos and check out \"Guest view\"."),
|
||||
"cl_guest_view_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Handing over your phone to show photos to a friend? Don\'t worry about them swiping too far.\nGuest view will lock them into the photos you select."),
|
||||
"Handing over your phone to show photos to a friend? Don\'t worry about them swiping too far. Guest view will lock them into the photos you select."),
|
||||
"cl_guest_view_title":
|
||||
MessageLookupByLibrary.simpleMessage("Guest View"),
|
||||
"cl_panorama_viewer_description": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -467,6 +470,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Clustering progress"),
|
||||
"codeAppliedPageTitle":
|
||||
MessageLookupByLibrary.simpleMessage("Code applied"),
|
||||
"codeChangeLimitReached": MessageLookupByLibrary.simpleMessage(
|
||||
"Sorry, you\'ve reached the limit of code changes."),
|
||||
"codeCopiedToClipboard":
|
||||
MessageLookupByLibrary.simpleMessage("Code copied to clipboard"),
|
||||
"codeUsedByYou":
|
||||
@@ -1575,6 +1580,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"unarchiveAlbum":
|
||||
MessageLookupByLibrary.simpleMessage("Unarchive album"),
|
||||
"unarchiving": MessageLookupByLibrary.simpleMessage("Unarchiving..."),
|
||||
"unavailableReferralCode": MessageLookupByLibrary.simpleMessage(
|
||||
"Sorry, this code is unavailable."),
|
||||
"uncategorized": MessageLookupByLibrary.simpleMessage("Uncategorized"),
|
||||
"unhide": MessageLookupByLibrary.simpleMessage("Unhide"),
|
||||
"unhideToAlbum":
|
||||
|
||||
44
mobile/lib/generated/l10n.dart
generated
44
mobile/lib/generated/l10n.dart
generated
@@ -2056,6 +2056,46 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Change your referral code`
|
||||
String get changeYourReferralCode {
|
||||
return Intl.message(
|
||||
'Change your referral code',
|
||||
name: 'changeYourReferralCode',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Change`
|
||||
String get change {
|
||||
return Intl.message(
|
||||
'Change',
|
||||
name: 'change',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Sorry, this code is unavailable.`
|
||||
String get unavailableReferralCode {
|
||||
return Intl.message(
|
||||
'Sorry, this code is unavailable.',
|
||||
name: 'unavailableReferralCode',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Sorry, you've reached the limit of code changes.`
|
||||
String get codeChangeLimitReached {
|
||||
return Intl.message(
|
||||
'Sorry, you\'ve reached the limit of code changes.',
|
||||
name: 'codeChangeLimitReached',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `{storageAmountInGB} GB`
|
||||
String storageInGB(Object storageAmountInGB) {
|
||||
return Intl.message(
|
||||
@@ -9365,10 +9405,10 @@ class S {
|
||||
);
|
||||
}
|
||||
|
||||
/// `Handing over your phone to show photos to a friend? Don't worry about them swiping too far.\nGuest view will lock them into the photos you select.`
|
||||
/// `Handing over your phone to show photos to a friend? Don't worry about them swiping too far. Guest view will lock them into the photos you select.`
|
||||
String get cl_guest_view_description {
|
||||
return Intl.message(
|
||||
'Handing over your phone to show photos to a friend? Don\'t worry about them swiping too far.\nGuest view will lock them into the photos you select.',
|
||||
'Handing over your phone to show photos to a friend? Don\'t worry about them swiping too far. Guest view will lock them into the photos you select.',
|
||||
name: 'cl_guest_view_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
|
||||
@@ -273,6 +273,10 @@
|
||||
"failedToApplyCode": "Failed to apply code",
|
||||
"enterReferralCode": "Enter referral code",
|
||||
"codeAppliedPageTitle": "Code applied",
|
||||
"changeYourReferralCode": "Change your referral code",
|
||||
"change": "Change",
|
||||
"unavailableReferralCode": "Sorry, this code is unavailable.",
|
||||
"codeChangeLimitReached": "Sorry, you've reached the limit of code changes.",
|
||||
"storageInGB": "{storageAmountInGB} GB",
|
||||
"claimed": "Claimed",
|
||||
"@claimed": {
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import "package:dio/dio.dart";
|
||||
import "package:dotted_border/dotted_border.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:logging/logging.dart";
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import "package:photos/services/storage_bonus_service.dart";
|
||||
import "package:photos/theme/ente_theme.dart";
|
||||
import "package:photos/utils/dialog_util.dart";
|
||||
|
||||
// Figma: https://www.figma.com/file/SYtMyLBs5SAOkTbfMMzhqt/ente-Visual-Design?node-id=11219%3A62974&t=BRCLJhxXP11Q3Wyw-0
|
||||
class ReferralCodeWidget extends StatelessWidget {
|
||||
final String codeValue;
|
||||
final bool shouldAllowEdit;
|
||||
final Function? notifyParent;
|
||||
|
||||
const ReferralCodeWidget(this.codeValue, {Key? key}) : super(key: key);
|
||||
const ReferralCodeWidget(
|
||||
this.codeValue, {
|
||||
this.shouldAllowEdit = false,
|
||||
this.notifyParent,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -37,11 +49,18 @@ class ReferralCodeWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Icon(
|
||||
Icons.adaptive.share,
|
||||
size: 22,
|
||||
color: colorScheme.strokeMuted,
|
||||
),
|
||||
shouldAllowEdit
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
showUpdateReferralCodeDialog(context);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
size: 22,
|
||||
color: colorScheme.strokeMuted,
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -49,4 +68,54 @@ class ReferralCodeWidget extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> showUpdateReferralCodeDialog(BuildContext context) async {
|
||||
final result = await showTextInputDialog(
|
||||
context,
|
||||
title: S.of(context).changeYourReferralCode,
|
||||
submitButtonLabel: S.of(context).change,
|
||||
hintText: S.of(context).enterCode,
|
||||
alwaysShowSuccessState: true,
|
||||
initialValue: codeValue,
|
||||
textCapitalization: TextCapitalization.characters,
|
||||
onSubmit: (String text) async {
|
||||
// indicates user cancelled the request
|
||||
if (text == "" || text.trim() == codeValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await StorageBonusService.instance
|
||||
.getGateway()
|
||||
.updateCode(text.trim().toUpperCase());
|
||||
notifyParent?.call();
|
||||
} catch (e, s) {
|
||||
Logger("ReferralCodeWidget").severe("Failed to update code", e, s);
|
||||
if (e is DioError) {
|
||||
if (e.response?.statusCode == 400) {
|
||||
await showInfoDialog(
|
||||
context,
|
||||
title: S.of(context).error,
|
||||
body: S.of(context).unavailableReferralCode,
|
||||
icon: Icons.error,
|
||||
);
|
||||
return;
|
||||
} else if (e.response?.statusCode == 429) {
|
||||
await showInfoDialog(
|
||||
context,
|
||||
title: S.of(context).error,
|
||||
body: S.of(context).codeChangeLimitReached,
|
||||
icon: Icons.error,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
},
|
||||
);
|
||||
if (result is Exception) {
|
||||
await showGenericErrorDialog(context: context, error: result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,41 +141,57 @@ class ReferralWidget extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: colorScheme.strokeFaint,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 12,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
S.of(context).referralStep1,
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: colorScheme.strokeFaint,
|
||||
width: 1,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
ReferralCodeWidget(referralView.code),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
S.of(context).referralStep2,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 12,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
S
|
||||
.of(context)
|
||||
.referralStep3(referralView.planInfo.storageInGB),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
S.of(context).referralStep1,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
ReferralCodeWidget(
|
||||
referralView.code,
|
||||
shouldAllowEdit: true,
|
||||
notifyParent: notifyParent,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
S.of(context).referralStep2,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
S.of(context).referralStep3(
|
||||
referralView.planInfo.storageInGB,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 8,
|
||||
top: 8,
|
||||
child: Icon(
|
||||
Icons.adaptive.share,
|
||||
color: colorScheme.blurStrokePressed,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
|
||||
Reference in New Issue
Block a user