1- import fsOperation from "fileSystem" ;
21import toast from "components/toast" ;
32import { addIntentHandler } from "handlers/intent" ;
4- import constants from "./constants" ;
53
64const loginEvents = {
75 listeners : new Set ( ) ,
@@ -18,70 +16,16 @@ const loginEvents = {
1816 } ,
1917} ;
2018
21- async function checkTokenFileExists ( ) {
22- return await fsOperation ( `${ DATA_STORAGE } .acode_token` ) . exists ( ) ;
23- }
24-
25- async function saveToken ( token ) {
26- try {
27- if ( await checkTokenFileExists ( ) ) {
28- await fsOperation ( `${ DATA_STORAGE } .acode_token` ) . writeFile ( token ) ;
29- } else {
30- await fsOperation ( DATA_STORAGE ) . createFile ( ".acode_token" , token ) ;
31- }
32- return true ;
33- } catch ( error ) {
34- console . error ( "Failed to save token" , error ) ;
35- return false ;
36- }
37- }
38-
39- async function getToken ( ) {
40- try {
41- if ( await checkTokenFileExists ( ) ) {
42- const token = await fsOperation ( `${ DATA_STORAGE } .acode_token` ) . readFile (
43- "utf8" ,
44- ) ;
45- return token ;
46- }
47- return null ;
48- } catch ( error ) {
49- console . error ( "Failed to get token" , error ) ;
50- return null ;
51- }
52- }
53-
54- async function deleteToken ( ) {
55- try {
56- if ( await checkTokenFileExists ( ) ) {
57- await fsOperation ( `${ DATA_STORAGE } .acode_token` ) . delete ( ) ;
58- return true ;
59- }
60- return false ;
61- } catch ( error ) {
62- console . error ( "Failed to delete token" , error ) ;
63- return false ;
64- }
65- }
66-
6719class AuthService {
6820 constructor ( ) {
6921 addIntentHandler ( this . onIntentReceiver . bind ( this ) ) ;
7022 }
7123
72- openLoginUrl ( ) {
73- try {
74- system . openInBrowser ( "https://acode.app/login?redirect=app" ) ;
75- } catch ( error ) {
76- console . error ( "Failed while opening login page." , error ) ;
77- }
78- }
79-
8024 async onIntentReceiver ( event ) {
8125 try {
8226 if ( event ?. module === "user" && event ?. action === "login" ) {
8327 if ( event ?. value ) {
84- saveToken ( event . value ) ;
28+ this . _exec ( "saveToken" , [ event . value ] ) ;
8529 toast ( "Logged in successfully" ) ;
8630
8731 setTimeout ( ( ) => {
@@ -96,10 +40,28 @@ class AuthService {
9640 }
9741 }
9842
43+ /**
44+ * Helper to wrap cordova.exec in a Promise
45+ */
46+ _exec ( action , args = [ ] ) {
47+ return new Promise ( ( resolve , reject ) => {
48+ cordova . exec ( resolve , reject , "Authenticator" , action , args ) ;
49+ } ) ;
50+ }
51+
52+ openLoginUrl ( ) {
53+ try {
54+ //todo use Custom tabs api for better ux
55+ system . openInBrowser ( "https://acode.app/login?redirect=app" ) ;
56+ } catch ( error ) {
57+ console . error ( "Failed while opening login page." , error ) ;
58+ }
59+ }
60+
9961 async logout ( ) {
10062 try {
101- const result = await deleteToken ( ) ;
102- return result ;
63+ await this . _exec ( "logout" ) ;
64+ return true ;
10365 } catch ( error ) {
10466 console . error ( "Failed to logout." , error ) ;
10567 return false ;
@@ -108,69 +70,19 @@ class AuthService {
10870
10971 async isLoggedIn ( ) {
11072 try {
111- const token = await getToken ( ) ;
112- if ( ! token ) return false ;
113-
114- return new Promise ( ( resolve , reject ) => {
115- cordova . plugin . http . sendRequest (
116- `${ constants . API_BASE } /login` ,
117- {
118- method : "GET" ,
119- headers : {
120- "x-auth-token" : token ,
121- } ,
122- } ,
123- ( response ) => {
124- resolve ( true ) ;
125- } ,
126- async ( error ) => {
127- if ( error . status === 401 ) {
128- await deleteToken ( ) ;
129- resolve ( false ) ;
130- } else {
131- console . error ( "Failed to check login status." , error ) ;
132- resolve ( false ) ;
133- }
134- } ,
135- ) ;
136- } ) ;
73+ // Native checks EncryptedPrefs and validates with API internally
74+ await this . _exec ( "isLoggedIn" ) ;
75+ return true ;
13776 } catch ( error ) {
138- console . error ( "Failed to check login status." , error ) ;
77+ // error is typically the status code (0 if no token, 401 if invalid)
13978 return false ;
14079 }
14180 }
14281
14382 async getUserInfo ( ) {
14483 try {
145- const token = await getToken ( ) ;
146- if ( ! token ) return null ;
147-
148- return new Promise ( ( resolve , reject ) => {
149- cordova . plugin . http . sendRequest (
150- `${ constants . API_BASE } /login` ,
151- {
152- method : "GET" ,
153- headers : {
154- "x-auth-token" : token ,
155- } ,
156- } ,
157- async ( response ) => {
158- if ( response . status === 200 ) {
159- resolve ( JSON . parse ( response . data ) ) ;
160- }
161- resolve ( null ) ;
162- } ,
163- async ( error ) => {
164- if ( error . status === 401 ) {
165- await deleteToken ( ) ;
166- resolve ( null ) ;
167- } else {
168- console . error ( "Failed to fetch user data." , error ) ;
169- resolve ( null ) ;
170- }
171- } ,
172- ) ;
173- } ) ;
84+ const data = await this . _exec ( "getUserInfo" ) ;
85+ return typeof data === "string" ? JSON . parse ( data ) : data ;
17486 } catch ( error ) {
17587 console . error ( "Failed to fetch user data." , error ) ;
17688 return null ;
@@ -180,49 +92,15 @@ class AuthService {
18092 async getAvatar ( ) {
18193 try {
18294 const userData = await this . getUserInfo ( ) ;
95+ console . log ( userData ) ;
18396 if ( ! userData ) return null ;
18497
18598 if ( userData . github ) {
18699 return `https://avatars.githubusercontent.com/${ userData . github } ` ;
187100 }
188101
189102 if ( userData . name ) {
190- const nameParts = userData . name . split ( " " ) ;
191- let initials = "" ;
192-
193- if ( nameParts . length >= 2 ) {
194- initials = `${ nameParts [ 0 ] [ 0 ] } ${ nameParts [ 1 ] [ 0 ] } ` . toUpperCase ( ) ;
195- } else {
196- initials = nameParts [ 0 ] [ 0 ] . toUpperCase ( ) ;
197- }
198-
199- // Create a data URL for text-based avatar
200- const canvas = document . createElement ( "canvas" ) ;
201- canvas . width = 100 ;
202- canvas . height = 100 ;
203- const ctx = canvas . getContext ( "2d" ) ;
204-
205- // Set background
206- // Array of colors to choose from
207- const colors = [
208- "#2196F3" ,
209- "#9C27B0" ,
210- "#E91E63" ,
211- "#009688" ,
212- "#4CAF50" ,
213- "#FF9800" ,
214- ] ;
215- ctx . fillStyle = colors [ Math . floor ( Math . random ( ) * colors . length ) ] ;
216- ctx . fillRect ( 0 , 0 , 100 , 100 ) ;
217-
218- // Add text
219- ctx . fillStyle = "#ffffff" ;
220- ctx . font = "bold 40px Arial" ;
221- ctx . textAlign = "center" ;
222- ctx . textBaseline = "middle" ;
223- ctx . fillText ( initials , 50 , 50 ) ;
224-
225- return canvas . toDataURL ( ) ;
103+ return this . _generateInitialsAvatar ( userData . name ) ;
226104 }
227105
228106 return null ;
@@ -231,6 +109,38 @@ class AuthService {
231109 return null ;
232110 }
233111 }
112+
113+ _generateInitialsAvatar ( name ) {
114+ const nameParts = name . split ( " " ) ;
115+ const initials =
116+ nameParts . length >= 2
117+ ? `${ nameParts [ 0 ] [ 0 ] } ${ nameParts [ 1 ] [ 0 ] } ` . toUpperCase ( )
118+ : nameParts [ 0 ] [ 0 ] . toUpperCase ( ) ;
119+
120+ const canvas = document . createElement ( "canvas" ) ;
121+ canvas . width = 100 ;
122+ canvas . height = 100 ;
123+ const ctx = canvas . getContext ( "2d" ) ;
124+
125+ const colors = [
126+ "#2196F3" ,
127+ "#9C27B0" ,
128+ "#E91E63" ,
129+ "#009688" ,
130+ "#4CAF50" ,
131+ "#FF9800" ,
132+ ] ;
133+ ctx . fillStyle = colors [ Math . floor ( Math . random ( ) * colors . length ) ] ;
134+ ctx . fillRect ( 0 , 0 , 100 , 100 ) ;
135+
136+ ctx . fillStyle = "#ffffff" ;
137+ ctx . font = "bold 40px Arial" ;
138+ ctx . textAlign = "center" ;
139+ ctx . textBaseline = "middle" ;
140+ ctx . fillText ( initials , 50 , 50 ) ;
141+
142+ return canvas . toDataURL ( ) ;
143+ }
234144}
235145
236146export default new AuthService ( ) ;
0 commit comments