Add option to claim a custom referral code (#2794)

This commit is contained in:
Neeraj Gupta
2024-08-21 18:09:46 +05:30
committed by GitHub
6 changed files with 185 additions and 40 deletions

View File

@@ -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);

View File

@@ -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":

View File

@@ -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: [],

View File

@@ -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": {

View File

@@ -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);
}
}
}

View File

@@ -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(