@followgate/js 0.12.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +111 -22
- package/dist/index.mjs +111 -22
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ type SocialAction = 'follow' | 'repost' | 'like';
|
|
|
12
12
|
interface TwitterConfig {
|
|
13
13
|
handle?: string;
|
|
14
14
|
overrideHandle?: string;
|
|
15
|
+
overridePostUrl?: string;
|
|
15
16
|
tweetId?: string;
|
|
16
17
|
username?: string;
|
|
17
18
|
}
|
|
@@ -120,6 +121,24 @@ declare class FollowGateClient {
|
|
|
120
121
|
* 3. config.twitter.handle (legacy fallback, deprecated)
|
|
121
122
|
*/
|
|
122
123
|
private getTargetHandle;
|
|
124
|
+
/**
|
|
125
|
+
* Get target post URL/ID with priority:
|
|
126
|
+
* 1. config.twitter.overridePostUrl (explicit override)
|
|
127
|
+
* 2. serverConfig.targetPostUrl (from Dashboard)
|
|
128
|
+
* 3. config.twitter.tweetId (legacy fallback, deprecated)
|
|
129
|
+
*/
|
|
130
|
+
private getTargetPostUrl;
|
|
131
|
+
/**
|
|
132
|
+
* Extract post ID from URL or return as-is if already an ID
|
|
133
|
+
* Supports: Tweet ID, Twitter/X URLs
|
|
134
|
+
*/
|
|
135
|
+
private extractPostId;
|
|
136
|
+
/**
|
|
137
|
+
* Check if repost step should be shown based on:
|
|
138
|
+
* 1. serverConfig.actions includes 'repost'
|
|
139
|
+
* 2. A valid postUrl is available
|
|
140
|
+
*/
|
|
141
|
+
private shouldShowRepostStep;
|
|
123
142
|
private renderUsernameStep;
|
|
124
143
|
private handleUsernameSubmit;
|
|
125
144
|
private renderFollowStep;
|
|
@@ -147,9 +166,14 @@ declare class FollowGateClient {
|
|
|
147
166
|
*/
|
|
148
167
|
hasUsername(): boolean;
|
|
149
168
|
/**
|
|
150
|
-
* Clear stored session
|
|
169
|
+
* Clear stored session (user, actions, and unlock status)
|
|
151
170
|
*/
|
|
152
171
|
reset(): void;
|
|
172
|
+
/**
|
|
173
|
+
* Clear only the unlock status (keeps user and actions)
|
|
174
|
+
* Useful for allowing users to go through the flow again
|
|
175
|
+
*/
|
|
176
|
+
clearUnlockStatus(): void;
|
|
153
177
|
getFollowUrl(platform: Platform, target: string): string;
|
|
154
178
|
getRepostUrl(platform: Platform, target: string): string;
|
|
155
179
|
getLikeUrl(platform: Platform, target: string): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ type SocialAction = 'follow' | 'repost' | 'like';
|
|
|
12
12
|
interface TwitterConfig {
|
|
13
13
|
handle?: string;
|
|
14
14
|
overrideHandle?: string;
|
|
15
|
+
overridePostUrl?: string;
|
|
15
16
|
tweetId?: string;
|
|
16
17
|
username?: string;
|
|
17
18
|
}
|
|
@@ -120,6 +121,24 @@ declare class FollowGateClient {
|
|
|
120
121
|
* 3. config.twitter.handle (legacy fallback, deprecated)
|
|
121
122
|
*/
|
|
122
123
|
private getTargetHandle;
|
|
124
|
+
/**
|
|
125
|
+
* Get target post URL/ID with priority:
|
|
126
|
+
* 1. config.twitter.overridePostUrl (explicit override)
|
|
127
|
+
* 2. serverConfig.targetPostUrl (from Dashboard)
|
|
128
|
+
* 3. config.twitter.tweetId (legacy fallback, deprecated)
|
|
129
|
+
*/
|
|
130
|
+
private getTargetPostUrl;
|
|
131
|
+
/**
|
|
132
|
+
* Extract post ID from URL or return as-is if already an ID
|
|
133
|
+
* Supports: Tweet ID, Twitter/X URLs
|
|
134
|
+
*/
|
|
135
|
+
private extractPostId;
|
|
136
|
+
/**
|
|
137
|
+
* Check if repost step should be shown based on:
|
|
138
|
+
* 1. serverConfig.actions includes 'repost'
|
|
139
|
+
* 2. A valid postUrl is available
|
|
140
|
+
*/
|
|
141
|
+
private shouldShowRepostStep;
|
|
123
142
|
private renderUsernameStep;
|
|
124
143
|
private handleUsernameSubmit;
|
|
125
144
|
private renderFollowStep;
|
|
@@ -147,9 +166,14 @@ declare class FollowGateClient {
|
|
|
147
166
|
*/
|
|
148
167
|
hasUsername(): boolean;
|
|
149
168
|
/**
|
|
150
|
-
* Clear stored session
|
|
169
|
+
* Clear stored session (user, actions, and unlock status)
|
|
151
170
|
*/
|
|
152
171
|
reset(): void;
|
|
172
|
+
/**
|
|
173
|
+
* Clear only the unlock status (keeps user and actions)
|
|
174
|
+
* Useful for allowing users to go through the flow again
|
|
175
|
+
*/
|
|
176
|
+
clearUnlockStatus(): void;
|
|
153
177
|
getFollowUrl(platform: Platform, target: string): string;
|
|
154
178
|
getRepostUrl(platform: Platform, target: string): string;
|
|
155
179
|
getLikeUrl(platform: Platform, target: string): string;
|
package/dist/index.js
CHANGED
|
@@ -606,7 +606,11 @@ var FollowGateClient = class {
|
|
|
606
606
|
}
|
|
607
607
|
if (this.isUnlocked()) {
|
|
608
608
|
if (this.config.debug) {
|
|
609
|
-
console.log(
|
|
609
|
+
console.log(
|
|
610
|
+
"[FollowGate] Modal skipped - user already unlocked.",
|
|
611
|
+
"Call FollowGate.reset() to clear unlock status.",
|
|
612
|
+
this.config.userId ? `(userId: ${this.config.userId})` : "(no userId set)"
|
|
613
|
+
);
|
|
610
614
|
}
|
|
611
615
|
this.config.onComplete?.();
|
|
612
616
|
return;
|
|
@@ -709,11 +713,68 @@ var FollowGateClient = class {
|
|
|
709
713
|
}
|
|
710
714
|
return null;
|
|
711
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Get target post URL/ID with priority:
|
|
718
|
+
* 1. config.twitter.overridePostUrl (explicit override)
|
|
719
|
+
* 2. serverConfig.targetPostUrl (from Dashboard)
|
|
720
|
+
* 3. config.twitter.tweetId (legacy fallback, deprecated)
|
|
721
|
+
*/
|
|
722
|
+
getTargetPostUrl() {
|
|
723
|
+
if (this.config?.twitter?.overridePostUrl) {
|
|
724
|
+
return this.extractPostId(this.config.twitter.overridePostUrl);
|
|
725
|
+
}
|
|
726
|
+
if (this.serverConfig?.targetPostUrl) {
|
|
727
|
+
return this.extractPostId(this.serverConfig.targetPostUrl);
|
|
728
|
+
}
|
|
729
|
+
if (this.config?.twitter?.tweetId) {
|
|
730
|
+
return this.config.twitter.tweetId;
|
|
731
|
+
}
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Extract post ID from URL or return as-is if already an ID
|
|
736
|
+
* Supports: Tweet ID, Twitter/X URLs
|
|
737
|
+
*/
|
|
738
|
+
extractPostId(input) {
|
|
739
|
+
if (!input) return null;
|
|
740
|
+
const trimmed = input.trim();
|
|
741
|
+
if (/^\d+$/.test(trimmed)) {
|
|
742
|
+
return trimmed;
|
|
743
|
+
}
|
|
744
|
+
const twitterMatch = trimmed.match(
|
|
745
|
+
/(?:twitter|x)\.com\/\w+\/status\/(\d+)/
|
|
746
|
+
);
|
|
747
|
+
if (twitterMatch) {
|
|
748
|
+
return twitterMatch[1];
|
|
749
|
+
}
|
|
750
|
+
return trimmed;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Check if repost step should be shown based on:
|
|
754
|
+
* 1. serverConfig.actions includes 'repost'
|
|
755
|
+
* 2. A valid postUrl is available
|
|
756
|
+
*/
|
|
757
|
+
shouldShowRepostStep() {
|
|
758
|
+
const postUrl = this.getTargetPostUrl();
|
|
759
|
+
const actionsIncludeRepost = this.serverConfig?.actions?.includes("repost");
|
|
760
|
+
if (actionsIncludeRepost && !postUrl) {
|
|
761
|
+
console.warn(
|
|
762
|
+
"[FollowGate] REPOST action configured but no targetPostUrl available.",
|
|
763
|
+
"Set targetPostUrl in Dashboard or use overridePostUrl in config.",
|
|
764
|
+
"Skipping repost step."
|
|
765
|
+
);
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
if (this.config?.twitter?.tweetId) {
|
|
769
|
+
return true;
|
|
770
|
+
}
|
|
771
|
+
return !!actionsIncludeRepost && !!postUrl;
|
|
772
|
+
}
|
|
712
773
|
renderUsernameStep() {
|
|
713
774
|
const content = this.getContentElement();
|
|
714
775
|
if (!content) return;
|
|
715
776
|
const handle = this.getTargetHandle();
|
|
716
|
-
const hasRepost =
|
|
777
|
+
const hasRepost = this.shouldShowRepostStep();
|
|
717
778
|
const allowSkip = this.serverConfig?.allowSkip ?? false;
|
|
718
779
|
const welcomeTitle = this.serverConfig?.welcomeTitle || "Unlock Free Access";
|
|
719
780
|
const welcomeMessage = this.serverConfig?.welcomeMessage || "Enter your X username to get started";
|
|
@@ -775,7 +836,7 @@ var FollowGateClient = class {
|
|
|
775
836
|
);
|
|
776
837
|
return;
|
|
777
838
|
}
|
|
778
|
-
const hasRepost =
|
|
839
|
+
const hasRepost = this.shouldShowRepostStep();
|
|
779
840
|
const defaultTitle = hasRepost ? "Step 1: Follow" : "Follow to Continue";
|
|
780
841
|
const defaultMessage = `Follow @${handle} on X`;
|
|
781
842
|
const title = this.serverConfig?.welcomeTitle || defaultTitle;
|
|
@@ -810,8 +871,7 @@ var FollowGateClient = class {
|
|
|
810
871
|
});
|
|
811
872
|
}
|
|
812
873
|
handleSkipFollow() {
|
|
813
|
-
if (
|
|
814
|
-
if (this.config.twitter.tweetId) {
|
|
874
|
+
if (this.shouldShowRepostStep()) {
|
|
815
875
|
this.renderRepostStep();
|
|
816
876
|
} else {
|
|
817
877
|
this.renderConfirmStep();
|
|
@@ -882,7 +942,7 @@ var FollowGateClient = class {
|
|
|
882
942
|
action: "follow",
|
|
883
943
|
target: handle
|
|
884
944
|
});
|
|
885
|
-
if (this.
|
|
945
|
+
if (this.shouldShowRepostStep()) {
|
|
886
946
|
this.renderRepostStep();
|
|
887
947
|
} else {
|
|
888
948
|
this.renderConfirmStep();
|
|
@@ -890,7 +950,8 @@ var FollowGateClient = class {
|
|
|
890
950
|
}
|
|
891
951
|
renderRepostStep() {
|
|
892
952
|
const content = this.getContentElement();
|
|
893
|
-
|
|
953
|
+
const postId = this.getTargetPostUrl();
|
|
954
|
+
if (!content || !postId) return;
|
|
894
955
|
content.innerHTML = `
|
|
895
956
|
${this.renderStepIndicator(2)}
|
|
896
957
|
<div class="fg-icon-box fg-success">
|
|
@@ -921,12 +982,12 @@ var FollowGateClient = class {
|
|
|
921
982
|
});
|
|
922
983
|
}
|
|
923
984
|
handleRepostClick() {
|
|
924
|
-
|
|
925
|
-
|
|
985
|
+
const postId = this.getTargetPostUrl();
|
|
986
|
+
if (!postId) return;
|
|
926
987
|
this.openIntent({
|
|
927
988
|
platform: "twitter",
|
|
928
989
|
action: "repost",
|
|
929
|
-
target:
|
|
990
|
+
target: postId
|
|
930
991
|
});
|
|
931
992
|
this.showRepostConfirmation();
|
|
932
993
|
}
|
|
@@ -976,11 +1037,12 @@ var FollowGateClient = class {
|
|
|
976
1037
|
}
|
|
977
1038
|
}
|
|
978
1039
|
async handleRepostConfirm() {
|
|
979
|
-
|
|
1040
|
+
const postId = this.getTargetPostUrl();
|
|
1041
|
+
if (!postId) return;
|
|
980
1042
|
await this.complete({
|
|
981
1043
|
platform: "twitter",
|
|
982
1044
|
action: "repost",
|
|
983
|
-
target:
|
|
1045
|
+
target: postId
|
|
984
1046
|
});
|
|
985
1047
|
this.renderConfirmStep();
|
|
986
1048
|
}
|
|
@@ -988,15 +1050,27 @@ var FollowGateClient = class {
|
|
|
988
1050
|
const content = this.getContentElement();
|
|
989
1051
|
if (!content) return;
|
|
990
1052
|
const username = this.currentUser?.username;
|
|
1053
|
+
const targetHandle = this.getTargetHandle();
|
|
1054
|
+
const postId = this.getTargetPostUrl();
|
|
991
1055
|
const successTitle = this.serverConfig?.successTitle || "Almost done!";
|
|
992
1056
|
const successMessage = this.serverConfig?.successMessage || null;
|
|
1057
|
+
const hasFollow = targetHandle !== null;
|
|
1058
|
+
const hasRepost = postId !== null;
|
|
1059
|
+
let verifyText = "Verifying";
|
|
1060
|
+
if (hasFollow && hasRepost) {
|
|
1061
|
+
verifyText = "Verifying follow & repost";
|
|
1062
|
+
} else if (hasFollow) {
|
|
1063
|
+
verifyText = "Verifying follow";
|
|
1064
|
+
} else if (hasRepost) {
|
|
1065
|
+
verifyText = "Verifying repost";
|
|
1066
|
+
}
|
|
993
1067
|
content.innerHTML = `
|
|
994
1068
|
<h2 class="fg-title">${this.escapeHtml(successTitle)}</h2>
|
|
995
1069
|
${successMessage ? `<p class="fg-subtitle" style="margin-bottom: 16px;">${this.escapeHtml(successMessage)}</p>` : ""}
|
|
996
1070
|
<div class="fg-verify-box">
|
|
997
1071
|
<div class="fg-verify-box-left">
|
|
998
1072
|
<div class="fg-verify-spinner"></div>
|
|
999
|
-
<span class="fg-verify-text"
|
|
1073
|
+
<span class="fg-verify-text">${verifyText}</span>
|
|
1000
1074
|
</div>
|
|
1001
1075
|
${username ? `
|
|
1002
1076
|
<div class="fg-user-badge" style="margin: 0; padding: 4px 10px; gap: 6px;">
|
|
@@ -1014,13 +1088,15 @@ var FollowGateClient = class {
|
|
|
1014
1088
|
${ICONS.check}
|
|
1015
1089
|
Got it
|
|
1016
1090
|
</button>
|
|
1017
|
-
${
|
|
1091
|
+
${hasFollow || hasRepost ? `
|
|
1018
1092
|
<div class="fg-btn-row">
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1093
|
+
${hasFollow ? `
|
|
1094
|
+
<button class="fg-btn fg-btn-secondary" id="fg-redo-follow">
|
|
1095
|
+
${ICONS.x}
|
|
1096
|
+
Open follow
|
|
1097
|
+
</button>
|
|
1098
|
+
` : ""}
|
|
1099
|
+
${hasRepost ? `
|
|
1024
1100
|
<button class="fg-btn fg-btn-secondary" id="fg-redo-repost">
|
|
1025
1101
|
${ICONS.repost}
|
|
1026
1102
|
Open repost
|
|
@@ -1043,11 +1119,12 @@ var FollowGateClient = class {
|
|
|
1043
1119
|
}
|
|
1044
1120
|
});
|
|
1045
1121
|
document.getElementById("fg-redo-repost")?.addEventListener("click", () => {
|
|
1046
|
-
|
|
1122
|
+
const repostId = this.getTargetPostUrl();
|
|
1123
|
+
if (repostId) {
|
|
1047
1124
|
this.openIntent({
|
|
1048
1125
|
platform: "twitter",
|
|
1049
1126
|
action: "repost",
|
|
1050
|
-
target:
|
|
1127
|
+
target: repostId
|
|
1051
1128
|
});
|
|
1052
1129
|
}
|
|
1053
1130
|
});
|
|
@@ -1111,7 +1188,7 @@ var FollowGateClient = class {
|
|
|
1111
1188
|
return this.currentUser !== null;
|
|
1112
1189
|
}
|
|
1113
1190
|
/**
|
|
1114
|
-
* Clear stored session
|
|
1191
|
+
* Clear stored session (user, actions, and unlock status)
|
|
1115
1192
|
*/
|
|
1116
1193
|
reset() {
|
|
1117
1194
|
this.currentUser = null;
|
|
@@ -1125,6 +1202,18 @@ var FollowGateClient = class {
|
|
|
1125
1202
|
console.log("[FollowGate] Session reset");
|
|
1126
1203
|
}
|
|
1127
1204
|
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Clear only the unlock status (keeps user and actions)
|
|
1207
|
+
* Useful for allowing users to go through the flow again
|
|
1208
|
+
*/
|
|
1209
|
+
clearUnlockStatus() {
|
|
1210
|
+
if (typeof localStorage !== "undefined") {
|
|
1211
|
+
localStorage.removeItem(this.getStorageKey("followgate_unlocked"));
|
|
1212
|
+
}
|
|
1213
|
+
if (this.config?.debug) {
|
|
1214
|
+
console.log("[FollowGate] Unlock status cleared");
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1128
1217
|
// ============================================
|
|
1129
1218
|
// Intent URL Methods
|
|
1130
1219
|
// ============================================
|
package/dist/index.mjs
CHANGED
|
@@ -580,7 +580,11 @@ var FollowGateClient = class {
|
|
|
580
580
|
}
|
|
581
581
|
if (this.isUnlocked()) {
|
|
582
582
|
if (this.config.debug) {
|
|
583
|
-
console.log(
|
|
583
|
+
console.log(
|
|
584
|
+
"[FollowGate] Modal skipped - user already unlocked.",
|
|
585
|
+
"Call FollowGate.reset() to clear unlock status.",
|
|
586
|
+
this.config.userId ? `(userId: ${this.config.userId})` : "(no userId set)"
|
|
587
|
+
);
|
|
584
588
|
}
|
|
585
589
|
this.config.onComplete?.();
|
|
586
590
|
return;
|
|
@@ -683,11 +687,68 @@ var FollowGateClient = class {
|
|
|
683
687
|
}
|
|
684
688
|
return null;
|
|
685
689
|
}
|
|
690
|
+
/**
|
|
691
|
+
* Get target post URL/ID with priority:
|
|
692
|
+
* 1. config.twitter.overridePostUrl (explicit override)
|
|
693
|
+
* 2. serverConfig.targetPostUrl (from Dashboard)
|
|
694
|
+
* 3. config.twitter.tweetId (legacy fallback, deprecated)
|
|
695
|
+
*/
|
|
696
|
+
getTargetPostUrl() {
|
|
697
|
+
if (this.config?.twitter?.overridePostUrl) {
|
|
698
|
+
return this.extractPostId(this.config.twitter.overridePostUrl);
|
|
699
|
+
}
|
|
700
|
+
if (this.serverConfig?.targetPostUrl) {
|
|
701
|
+
return this.extractPostId(this.serverConfig.targetPostUrl);
|
|
702
|
+
}
|
|
703
|
+
if (this.config?.twitter?.tweetId) {
|
|
704
|
+
return this.config.twitter.tweetId;
|
|
705
|
+
}
|
|
706
|
+
return null;
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Extract post ID from URL or return as-is if already an ID
|
|
710
|
+
* Supports: Tweet ID, Twitter/X URLs
|
|
711
|
+
*/
|
|
712
|
+
extractPostId(input) {
|
|
713
|
+
if (!input) return null;
|
|
714
|
+
const trimmed = input.trim();
|
|
715
|
+
if (/^\d+$/.test(trimmed)) {
|
|
716
|
+
return trimmed;
|
|
717
|
+
}
|
|
718
|
+
const twitterMatch = trimmed.match(
|
|
719
|
+
/(?:twitter|x)\.com\/\w+\/status\/(\d+)/
|
|
720
|
+
);
|
|
721
|
+
if (twitterMatch) {
|
|
722
|
+
return twitterMatch[1];
|
|
723
|
+
}
|
|
724
|
+
return trimmed;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Check if repost step should be shown based on:
|
|
728
|
+
* 1. serverConfig.actions includes 'repost'
|
|
729
|
+
* 2. A valid postUrl is available
|
|
730
|
+
*/
|
|
731
|
+
shouldShowRepostStep() {
|
|
732
|
+
const postUrl = this.getTargetPostUrl();
|
|
733
|
+
const actionsIncludeRepost = this.serverConfig?.actions?.includes("repost");
|
|
734
|
+
if (actionsIncludeRepost && !postUrl) {
|
|
735
|
+
console.warn(
|
|
736
|
+
"[FollowGate] REPOST action configured but no targetPostUrl available.",
|
|
737
|
+
"Set targetPostUrl in Dashboard or use overridePostUrl in config.",
|
|
738
|
+
"Skipping repost step."
|
|
739
|
+
);
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
if (this.config?.twitter?.tweetId) {
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
return !!actionsIncludeRepost && !!postUrl;
|
|
746
|
+
}
|
|
686
747
|
renderUsernameStep() {
|
|
687
748
|
const content = this.getContentElement();
|
|
688
749
|
if (!content) return;
|
|
689
750
|
const handle = this.getTargetHandle();
|
|
690
|
-
const hasRepost =
|
|
751
|
+
const hasRepost = this.shouldShowRepostStep();
|
|
691
752
|
const allowSkip = this.serverConfig?.allowSkip ?? false;
|
|
692
753
|
const welcomeTitle = this.serverConfig?.welcomeTitle || "Unlock Free Access";
|
|
693
754
|
const welcomeMessage = this.serverConfig?.welcomeMessage || "Enter your X username to get started";
|
|
@@ -749,7 +810,7 @@ var FollowGateClient = class {
|
|
|
749
810
|
);
|
|
750
811
|
return;
|
|
751
812
|
}
|
|
752
|
-
const hasRepost =
|
|
813
|
+
const hasRepost = this.shouldShowRepostStep();
|
|
753
814
|
const defaultTitle = hasRepost ? "Step 1: Follow" : "Follow to Continue";
|
|
754
815
|
const defaultMessage = `Follow @${handle} on X`;
|
|
755
816
|
const title = this.serverConfig?.welcomeTitle || defaultTitle;
|
|
@@ -784,8 +845,7 @@ var FollowGateClient = class {
|
|
|
784
845
|
});
|
|
785
846
|
}
|
|
786
847
|
handleSkipFollow() {
|
|
787
|
-
if (
|
|
788
|
-
if (this.config.twitter.tweetId) {
|
|
848
|
+
if (this.shouldShowRepostStep()) {
|
|
789
849
|
this.renderRepostStep();
|
|
790
850
|
} else {
|
|
791
851
|
this.renderConfirmStep();
|
|
@@ -856,7 +916,7 @@ var FollowGateClient = class {
|
|
|
856
916
|
action: "follow",
|
|
857
917
|
target: handle
|
|
858
918
|
});
|
|
859
|
-
if (this.
|
|
919
|
+
if (this.shouldShowRepostStep()) {
|
|
860
920
|
this.renderRepostStep();
|
|
861
921
|
} else {
|
|
862
922
|
this.renderConfirmStep();
|
|
@@ -864,7 +924,8 @@ var FollowGateClient = class {
|
|
|
864
924
|
}
|
|
865
925
|
renderRepostStep() {
|
|
866
926
|
const content = this.getContentElement();
|
|
867
|
-
|
|
927
|
+
const postId = this.getTargetPostUrl();
|
|
928
|
+
if (!content || !postId) return;
|
|
868
929
|
content.innerHTML = `
|
|
869
930
|
${this.renderStepIndicator(2)}
|
|
870
931
|
<div class="fg-icon-box fg-success">
|
|
@@ -895,12 +956,12 @@ var FollowGateClient = class {
|
|
|
895
956
|
});
|
|
896
957
|
}
|
|
897
958
|
handleRepostClick() {
|
|
898
|
-
|
|
899
|
-
|
|
959
|
+
const postId = this.getTargetPostUrl();
|
|
960
|
+
if (!postId) return;
|
|
900
961
|
this.openIntent({
|
|
901
962
|
platform: "twitter",
|
|
902
963
|
action: "repost",
|
|
903
|
-
target:
|
|
964
|
+
target: postId
|
|
904
965
|
});
|
|
905
966
|
this.showRepostConfirmation();
|
|
906
967
|
}
|
|
@@ -950,11 +1011,12 @@ var FollowGateClient = class {
|
|
|
950
1011
|
}
|
|
951
1012
|
}
|
|
952
1013
|
async handleRepostConfirm() {
|
|
953
|
-
|
|
1014
|
+
const postId = this.getTargetPostUrl();
|
|
1015
|
+
if (!postId) return;
|
|
954
1016
|
await this.complete({
|
|
955
1017
|
platform: "twitter",
|
|
956
1018
|
action: "repost",
|
|
957
|
-
target:
|
|
1019
|
+
target: postId
|
|
958
1020
|
});
|
|
959
1021
|
this.renderConfirmStep();
|
|
960
1022
|
}
|
|
@@ -962,15 +1024,27 @@ var FollowGateClient = class {
|
|
|
962
1024
|
const content = this.getContentElement();
|
|
963
1025
|
if (!content) return;
|
|
964
1026
|
const username = this.currentUser?.username;
|
|
1027
|
+
const targetHandle = this.getTargetHandle();
|
|
1028
|
+
const postId = this.getTargetPostUrl();
|
|
965
1029
|
const successTitle = this.serverConfig?.successTitle || "Almost done!";
|
|
966
1030
|
const successMessage = this.serverConfig?.successMessage || null;
|
|
1031
|
+
const hasFollow = targetHandle !== null;
|
|
1032
|
+
const hasRepost = postId !== null;
|
|
1033
|
+
let verifyText = "Verifying";
|
|
1034
|
+
if (hasFollow && hasRepost) {
|
|
1035
|
+
verifyText = "Verifying follow & repost";
|
|
1036
|
+
} else if (hasFollow) {
|
|
1037
|
+
verifyText = "Verifying follow";
|
|
1038
|
+
} else if (hasRepost) {
|
|
1039
|
+
verifyText = "Verifying repost";
|
|
1040
|
+
}
|
|
967
1041
|
content.innerHTML = `
|
|
968
1042
|
<h2 class="fg-title">${this.escapeHtml(successTitle)}</h2>
|
|
969
1043
|
${successMessage ? `<p class="fg-subtitle" style="margin-bottom: 16px;">${this.escapeHtml(successMessage)}</p>` : ""}
|
|
970
1044
|
<div class="fg-verify-box">
|
|
971
1045
|
<div class="fg-verify-box-left">
|
|
972
1046
|
<div class="fg-verify-spinner"></div>
|
|
973
|
-
<span class="fg-verify-text"
|
|
1047
|
+
<span class="fg-verify-text">${verifyText}</span>
|
|
974
1048
|
</div>
|
|
975
1049
|
${username ? `
|
|
976
1050
|
<div class="fg-user-badge" style="margin: 0; padding: 4px 10px; gap: 6px;">
|
|
@@ -988,13 +1062,15 @@ var FollowGateClient = class {
|
|
|
988
1062
|
${ICONS.check}
|
|
989
1063
|
Got it
|
|
990
1064
|
</button>
|
|
991
|
-
${
|
|
1065
|
+
${hasFollow || hasRepost ? `
|
|
992
1066
|
<div class="fg-btn-row">
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1067
|
+
${hasFollow ? `
|
|
1068
|
+
<button class="fg-btn fg-btn-secondary" id="fg-redo-follow">
|
|
1069
|
+
${ICONS.x}
|
|
1070
|
+
Open follow
|
|
1071
|
+
</button>
|
|
1072
|
+
` : ""}
|
|
1073
|
+
${hasRepost ? `
|
|
998
1074
|
<button class="fg-btn fg-btn-secondary" id="fg-redo-repost">
|
|
999
1075
|
${ICONS.repost}
|
|
1000
1076
|
Open repost
|
|
@@ -1017,11 +1093,12 @@ var FollowGateClient = class {
|
|
|
1017
1093
|
}
|
|
1018
1094
|
});
|
|
1019
1095
|
document.getElementById("fg-redo-repost")?.addEventListener("click", () => {
|
|
1020
|
-
|
|
1096
|
+
const repostId = this.getTargetPostUrl();
|
|
1097
|
+
if (repostId) {
|
|
1021
1098
|
this.openIntent({
|
|
1022
1099
|
platform: "twitter",
|
|
1023
1100
|
action: "repost",
|
|
1024
|
-
target:
|
|
1101
|
+
target: repostId
|
|
1025
1102
|
});
|
|
1026
1103
|
}
|
|
1027
1104
|
});
|
|
@@ -1085,7 +1162,7 @@ var FollowGateClient = class {
|
|
|
1085
1162
|
return this.currentUser !== null;
|
|
1086
1163
|
}
|
|
1087
1164
|
/**
|
|
1088
|
-
* Clear stored session
|
|
1165
|
+
* Clear stored session (user, actions, and unlock status)
|
|
1089
1166
|
*/
|
|
1090
1167
|
reset() {
|
|
1091
1168
|
this.currentUser = null;
|
|
@@ -1099,6 +1176,18 @@ var FollowGateClient = class {
|
|
|
1099
1176
|
console.log("[FollowGate] Session reset");
|
|
1100
1177
|
}
|
|
1101
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Clear only the unlock status (keeps user and actions)
|
|
1181
|
+
* Useful for allowing users to go through the flow again
|
|
1182
|
+
*/
|
|
1183
|
+
clearUnlockStatus() {
|
|
1184
|
+
if (typeof localStorage !== "undefined") {
|
|
1185
|
+
localStorage.removeItem(this.getStorageKey("followgate_unlocked"));
|
|
1186
|
+
}
|
|
1187
|
+
if (this.config?.debug) {
|
|
1188
|
+
console.log("[FollowGate] Unlock status cleared");
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1102
1191
|
// ============================================
|
|
1103
1192
|
// Intent URL Methods
|
|
1104
1193
|
// ============================================
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@followgate/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "FollowGate SDK - Grow your audience with every download. Require social actions (follow, repost) before users can access your app.",
|
|
5
5
|
"author": "FollowGate <hello@followgate.app>",
|
|
6
6
|
"homepage": "https://followgate.app",
|