forked from jlyman/react-native-rating-requestor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
157 lines (143 loc) · 4.77 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import React, { Platform, Alert, Linking } from "react-native";
import RatingsData from "./RatingsData";
export const buttonTypes = {
NEUTRAL_DELAY: "NEUTRAL_DELAY",
NEGATIVE_DECLINE: "NEGATIVE_DECLINE",
POSITIVE_ACCEPT: "POSITIVE_ACCEPT"
};
const _config = {
title: "Rate Me",
message:
"We hope you're loving our app. If you are, would you mind taking a quick moment to leave us a positive review?",
appStoreId: null,
actionLabels: {
decline: "Don't ask again",
delay: "Maybe later...",
accept: "Sure!"
},
timingFunction: function(currentCount) {
return (
currentCount > 1 &&
(Math.log(currentCount) / Math.log(3)).toFixed(4) % 1 == 0
);
},
buttonOrder: {
ios: [
buttonTypes.NEGATIVE_DECLINE,
buttonTypes.NEUTRAL_DELAY,
buttonTypes.POSITIVE_ACCEPT
],
android: [
buttonTypes.NEGATIVE_DECLINE,
buttonTypes.NEUTRAL_DELAY,
buttonTypes.POSITIVE_ACCEPT
]
},
shouldBoldLastButton: true,
storeAppName: 'appName',
storeCountry: 'us'
};
async function _isAwaitingRating() {
let timestamps = await RatingsData.getActionTimestamps();
// If no timestamps have been set yet we are still awaiting the user, return true
return timestamps.every(timestamp => {
return timestamp[1] === null;
});
}
/**
* Creates the RatingRequestor object you interact with
* @class
*/
export default class RatingRequestor {
/**
* @param {string} appStoreId - Required. The ID used in the app's respective app store
* @param {object} options - Optional. Override the defaults. Takes the following shape, with all elements being optional:
* {
* title: {string},
* message: {string},
* actionLabels: {
* decline: {string},
* delay: {string},
* accept: {string}
* },
* buttonOrder: {
* ios: [buttonTypes],
* android: [buttonTypes],
* }
* shouldBoldLastButton: {boolean},
* storeAppName: {string},
* storeCountry: {string},
* timingFunction: {func}
* }
*/
constructor(appStoreId, options) {
// Check for required options
if (!appStoreId) {
throw "You must specify your app's store ID on construction to use the Rating Requestor.";
}
// Merge defaults with user-supplied config
Object.assign(_config, options);
_config.appStoreId = appStoreId;
this.storeUrl = Platform.select({
ios: `https://itunes.apple.com/${_config.storeCountry}/app/${_config.storeAppName}/id${_config.appStoreId}`,
android: `https://play.google.com/store/apps/details?id=${_config.appStoreId}`,
});
}
/**
* Shows the rating dialog when called. Normally called by `handlePositiveEvent()`, but
* can be called on its own as well. Use caution when doing so--you don't want to ask
* the user for a rating too frequently or you might annoy them. (This is handy, however,
* if the user proactively seeks out something in your app to leave a rating, for example.)
*
* @param {function(didAppear: boolean, result: string)} callback Optional. Callback that reports whether the dialog appeared and what the result was.
*/
showRatingDialog(callback = () => {}) {
const buttonDefaults = {
NEGATIVE_DECLINE: {
text: _config.actionLabels.decline,
onPress: () => {
RatingsData.recordDecline();
callback(true, "decline");
}
},
NEUTRAL_DELAY: {
text: _config.actionLabels.delay,
onPress: () => {
callback(true, "delay");
}
},
POSITIVE_ACCEPT: {
text: _config.actionLabels.accept,
onPress: () => {
RatingsData.recordRated();
callback(true, "accept");
Linking.openURL(this.storeUrl);
},
style: "default",
}
};
const buttons = Platform.select(_config.buttonOrder).map(bo => buttonDefaults[bo]);
if (_config.shouldBoldLastButton) {
buttons[2].style = 'cancel';
}
Alert.alert(
_config.title,
_config.message,
buttons,
);
}
/**
* Call when a positive interaction has occurred within your application. Depending on the number
* of times this has occurred and your timing function, this may display a rating request dialog.
*
* @param {function(didAppear: boolean, result: string)} callback Optional. Callback that reports whether the dialog appeared and what the result was.
*/
async handlePositiveEvent(callback = () => {}) {
if (await _isAwaitingRating()) {
let currentCount = await RatingsData.incrementCount();
if (_config.timingFunction(currentCount)) {
this.showRatingDialog(callback);
} else callback(false);
} else callback(false);
}
}