-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix Google Login button disappearing issue (#3197)
### Purpose: The current Google login button occasionally disappears. The reason is that the Google script is loaded statically, meaning it is automatically loaded via the `<script>` tag when the page loads. This approach has a potential issue: if we want to use the `onGoogleLibraryLoad` callback function to confirm that the script has successfully loaded, we must ensure that the callback is defined before the script finishes loading. Otherwise, when the script completes loading, Google will check whether `onGoogleLibraryLoad` is defined. If it is not defined, the script load notification will be missed, and the Google login initialization logic will not execute. fix #3155 ### Changes: 1. To reduce the maintenance cost caused by frequent updates to the Google official API, we chose to implement Google login using the third-party library angularx-social-login instead of directly relying on the Google official API. 2. Added the dependency @abacritt/angularx-social-login (version 2.1.0). Please use `yarn install` to install it. 3. Additionally, a test file for the Google Login component has been added to verify whether the component initializes correctly after the script is successfully loaded. ### Demos: Before: https://github.com/user-attachments/assets/2717e6cb-d250-49e0-a09d-d3d11ffc7be3 After: https://github.com/user-attachments/assets/81d9e48b-02ee-48ad-8481-d7a50ce43ba0 --------- Co-authored-by: Chris <[email protected]> Co-authored-by: Xinyuan Lin <[email protected]>
- Loading branch information
1 parent
c5c0701
commit 58a214f
Showing
12 changed files
with
207 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 4 additions & 29 deletions
33
core/gui/src/app/common/service/user/google-auth.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,15 @@ | ||
import { Injectable } from "@angular/core"; | ||
import { Subject } from "rxjs"; | ||
import { Observable } from "rxjs"; | ||
import { HttpClient } from "@angular/common/http"; | ||
import { AppSettings } from "../../app-setting"; | ||
declare var window: any; | ||
export interface CredentialResponse { | ||
client_id: string; | ||
credential: string; | ||
select_by: string; | ||
} | ||
|
||
@Injectable({ | ||
providedIn: "root", | ||
}) | ||
export class GoogleAuthService { | ||
private _googleCredentialResponse = new Subject<CredentialResponse>(); | ||
constructor(private http: HttpClient) {} | ||
public googleAuthInit(parent: HTMLElement | null) { | ||
this.http.get(`${AppSettings.getApiEndpoint()}/auth/google/clientid`, { responseType: "text" }).subscribe({ | ||
next: response => { | ||
window.onGoogleLibraryLoad = () => { | ||
window.google.accounts.id.initialize({ | ||
client_id: response, | ||
callback: (auth: CredentialResponse) => { | ||
this._googleCredentialResponse.next(auth); | ||
}, | ||
}); | ||
window.google.accounts.id.renderButton(parent, { width: 200 }); | ||
window.google.accounts.id.prompt(); | ||
}; | ||
}, | ||
error: (err: unknown) => { | ||
console.error(err); | ||
}, | ||
}); | ||
} | ||
|
||
get googleCredentialResponse() { | ||
return this._googleCredentialResponse.asObservable(); | ||
getClientId(): Observable<string> { | ||
return this.http.get(`${AppSettings.getApiEndpoint()}/auth/google/clientid`, { responseType: "text" }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
core/gui/src/app/dashboard/component/dashboard.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { TestBed, ComponentFixture } from "@angular/core/testing"; | ||
import { DashboardComponent } from "./dashboard.component"; | ||
import { NO_ERRORS_SCHEMA, ChangeDetectorRef, NgZone, EventEmitter } from "@angular/core"; | ||
import { By } from "@angular/platform-browser"; | ||
import { of } from "rxjs"; | ||
|
||
import { UserService } from "../../common/service/user/user.service"; | ||
import { FlarumService } from "../service/user/flarum/flarum.service"; | ||
import { SocialAuthService } from "@abacritt/angularx-social-login"; | ||
import { | ||
Router, | ||
NavigationEnd, | ||
ActivatedRoute, | ||
ActivatedRouteSnapshot, | ||
UrlSegment, | ||
Params, | ||
Data, | ||
} from "@angular/router"; | ||
import { convertToParamMap } from "@angular/router"; | ||
|
||
describe("DashboardComponent", () => { | ||
let component: DashboardComponent; | ||
let fixture: ComponentFixture<DashboardComponent>; | ||
|
||
let userServiceMock: Partial<UserService>; | ||
let routerMock: Partial<Router>; | ||
let flarumServiceMock: Partial<FlarumService>; | ||
let cdrMock: Partial<ChangeDetectorRef>; | ||
let ngZoneMock: Partial<NgZone>; | ||
let socialAuthServiceMock: Partial<SocialAuthService>; | ||
let activatedRouteMock: Partial<ActivatedRoute>; | ||
|
||
const activatedRouteSnapshotMock: Partial<ActivatedRouteSnapshot> = { | ||
queryParams: {}, | ||
url: [] as UrlSegment[], | ||
params: {} as Params, | ||
fragment: null, | ||
data: {} as Data, | ||
paramMap: convertToParamMap({}), | ||
queryParamMap: convertToParamMap({}), | ||
outlet: "", | ||
routeConfig: null, | ||
root: null as any, | ||
parent: null as any, | ||
firstChild: null as any, | ||
children: [], | ||
pathFromRoot: [], | ||
}; | ||
|
||
beforeEach(async () => { | ||
userServiceMock = { | ||
isAdmin: jasmine.createSpy("isAdmin").and.returnValue(false), | ||
isLogin: jasmine.createSpy("isLogin").and.returnValue(false), | ||
userChanged: jasmine.createSpy("userChanged").and.returnValue(of(null)), | ||
}; | ||
|
||
routerMock = { | ||
events: of(new NavigationEnd(1, "/dashboard", "/dashboard")), | ||
url: "/dashboard", | ||
navigateByUrl: jasmine.createSpy("navigateByUrl"), | ||
}; | ||
|
||
flarumServiceMock = { | ||
auth: jasmine.createSpy("auth").and.returnValue(of({ token: "dummyToken" })), | ||
register: jasmine.createSpy("register").and.returnValue(of(null)), | ||
}; | ||
|
||
cdrMock = { | ||
detectChanges: jasmine.createSpy("detectChanges"), | ||
}; | ||
|
||
ngZoneMock = { | ||
hasPendingMicrotasks: false, | ||
hasPendingMacrotasks: false, | ||
onUnstable: new EventEmitter<any>(), | ||
onMicrotaskEmpty: new EventEmitter<any>(), | ||
onStable: new EventEmitter<any>(), | ||
onError: new EventEmitter<any>(), | ||
run: (fn: () => any) => fn(), | ||
runGuarded: (fn: () => any) => fn(), | ||
runOutsideAngular: (fn: () => any) => fn(), | ||
runTask: (fn: () => any) => fn(), | ||
}; | ||
|
||
socialAuthServiceMock = { | ||
authState: of(), | ||
}; | ||
|
||
activatedRouteMock = { | ||
snapshot: activatedRouteSnapshotMock as ActivatedRouteSnapshot, | ||
}; | ||
|
||
await TestBed.configureTestingModule({ | ||
declarations: [DashboardComponent], | ||
providers: [ | ||
{ provide: UserService, useValue: userServiceMock }, | ||
{ provide: Router, useValue: routerMock }, | ||
{ provide: FlarumService, useValue: flarumServiceMock }, | ||
{ provide: ChangeDetectorRef, useValue: cdrMock }, | ||
{ provide: NgZone, useValue: ngZoneMock }, | ||
{ provide: SocialAuthService, useValue: socialAuthServiceMock }, | ||
{ provide: ActivatedRoute, useValue: activatedRouteMock }, | ||
], | ||
schemas: [NO_ERRORS_SCHEMA], | ||
}).compileComponents(); | ||
}); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(DashboardComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it("should create the component", () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
it("should render Google sign-in button when user is NOT logged in", () => { | ||
(userServiceMock.isLogin as jasmine.Spy).and.returnValue(false); | ||
fixture.detectChanges(); | ||
|
||
const googleSignInBtn = fixture.debugElement.query(By.css("asl-google-signin-button")); | ||
expect(googleSignInBtn).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 0 additions & 35 deletions
35
core/gui/src/app/dashboard/component/user/google-login/google-login.component.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.