-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathindex.js
More file actions
162 lines (149 loc) · 4.93 KB
/
Copy pathindex.js
File metadata and controls
162 lines (149 loc) · 4.93 KB
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
158
159
160
161
162
import { Platform, Alert, Linking } from "react-native";
import * as StoreReview from 'react-native-store-review';
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: `market://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");
// This API is only available on iOS 10.3 or later
if (Platform.OS === 'ios') {
StoreReview.requestReview();
} else {
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);
}
}