Skip to content

Commit

Permalink
feat: support microsoft login
Browse files Browse the repository at this point in the history
  • Loading branch information
ci010 committed Dec 20, 2020
1 parent 5f1148b commit 410540d
Show file tree
Hide file tree
Showing 23 changed files with 1,204 additions and 614 deletions.
927 changes: 543 additions & 384 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"test": "jest"
},
"dependencies": {
"@azure/msal-node": "^1.0.0-beta.2",
"@vue/composition-api": "^1.0.0-beta.11",
"@xmcl/client": "2.0.6",
"@xmcl/core": "2.4.0",
Expand Down
23 changes: 15 additions & 8 deletions src/main/app/LauncherApp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LAUNCHER_NAME } from '@main/constant';
import { BrowserWindow, BrowserWindowConstructorOptions, Client, Dialog, Dock, Menu, MenuItem, MenuItemConstructorOptions, Notification, NotificationConstructorOptions, Tray } from '@main/engineBridge';
import { Client } from '@main/engineBridge';
import CredentialManager from '@main/manager/CredentialManager';
import LogManager from '@main/manager/LogManager';
import NetworkManager from '@main/manager/NetworkManager';
import ServiceManager from '@main/manager/ServiceManager';
Expand Down Expand Up @@ -59,9 +60,9 @@ export interface LauncherApp {
once(channel: 'minecraft-exit', listener: (exitStatus: { code: number; signal: string; crashReport: string; crashReportLocation: string; errorLog: string }) => void): this;
once(channel: 'minecraft-stdout', listener: (out: string) => void): this;
once(channel: 'minecraft-stderr', listener: (err: string) => void): this;
once(channel: 'microsoft-authorize-code', listener: (code: string) => void): this;
once(channel: 'microsoft-authorize-code', listener: (error?: Error, code?: string) => void): this;

emit(channel: 'microsoft-authorize-code', code: string): this;
emit(channel: 'microsoft-authorize-code', error?: Error, code?: string): this;
emit(channel: 'window-all-closed'): boolean;
emit(channel: 'engine-ready'): boolean;
emit(channel: 'store-ready', store: StaticStore<any>): boolean;
Expand Down Expand Up @@ -114,6 +115,8 @@ export abstract class LauncherApp extends EventEmitter {

readonly telemetryManager = new TelemetryManager(this);

readonly credentialManager = new CredentialManager(this);

readonly platform: Platform = getPlatform();

abstract readonly version: string;
Expand All @@ -122,9 +125,9 @@ export abstract class LauncherApp extends EventEmitter {

get isParking(): boolean { return this.parking; }

protected managers = [this.logManager, this.networkManager, this.taskManager, this.storeManager, this.serviceManager, this.telemetryManager];
protected managers = [this.logManager, this.networkManager, this.taskManager, this.storeManager, this.serviceManager, this.telemetryManager, this.credentialManager];

protected controller: LauncherAppController;
readonly controller: LauncherAppController;

constructor() {
super();
Expand Down Expand Up @@ -176,6 +179,12 @@ export abstract class LauncherApp extends EventEmitter {
*/
abstract showItemInFolder(path: string): void;

/**
* Handle the url activate the app
* @param url The url input
*/
abstract handleUrl(url: string): void;

/**
* Quit the app gentally.
*/
Expand All @@ -197,7 +206,7 @@ export abstract class LauncherApp extends EventEmitter {
/**
* Get the system provided path
*/
abstract getPath(key: string): string;
abstract getPath(key: 'home' | 'appData' | 'userData' | 'cache' | 'temp' | 'exe' | 'module' | 'desktop' | 'documents' | 'downloads' | 'music' | 'pictures' | 'videos' | 'logs' | 'pepperFlashSystemPlugin'): string;

/**
* Wait the engine ready
Expand Down Expand Up @@ -225,8 +234,6 @@ export abstract class LauncherApp extends EventEmitter {
*/
abstract installUpdateAndQuit(): Promise<void>;

abstract gainMicrosoftAuthCode(): Promise<string>;

abstract relaunch(): void;

log = (message: any, ...options: any[]) => { this.logManager.log(`[App] ${message}`, ...options); }
Expand Down
1 change: 1 addition & 0 deletions src/main/app/LauncherAppController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { StaticStore } from '@universal/util/staticStore';

export interface LauncherAppController {
processFirstLaunch(): Promise<string>;
requireFocus(): void;
engineReady(): Promise<void>;
dataReady(store: StaticStore<any>): Promise<void>;
}
2 changes: 1 addition & 1 deletion src/main/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export const AZURE_CDN_HOST = 'xmcl-release.azureedge.net';
export const BUILTIN_TRUSTED_SITES = Object.freeze(['https://www.java.com/download/']);
export const APP_INSIGHT_KEY = '294f3664-8208-4963-a2b0-62405ff9d48e';
export const MAX_RESOURCE_SIZE = 1024 * 1024 * 50;
export const CLIENT_ID = '';
export const CLIENT_ID = '1363d629-5b06-48a9-a5fb-c65de945f13e';
16 changes: 14 additions & 2 deletions src/main/electron/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class Controller implements LauncherAppController {
private store!: StaticStore<any>;

constructor(protected app: LauncherApp) { }

private setupBrowserLogger(ref: BrowserWindow, name: string) {
const stream = this.app.logManager.openWindowLog(name);
const levels = ['INFO', 'WARN', 'ERROR'];
Expand Down Expand Up @@ -66,9 +66,13 @@ export default class Controller implements LauncherAppController {
createMainWindow() {
const browser = new BrowserWindow({
title: 'KeyStone Launcher',
minWidth: 800,
minHeight: 580,
width: 800,
height: 580,
resizable: false,
maxWidth: 1600,
maxHeight: 1060,
resizable: true,
frame: false,
transparent: true,
hasShadow: false,
Expand Down Expand Up @@ -151,6 +155,14 @@ export default class Controller implements LauncherAppController {
this.setupRef = browser;
}

requireFocus(): void {
if (this.mainWin) {
this.mainWin.focus();
} else if (this.loggerWin) {
this.loggerWin.focus();
}
}

async requestOpenExternalUrl(url: string) {
const { t: $t } = this.i18n;
const result = await dialog.showMessageBox(this.mainWin!, {
Expand Down
54 changes: 31 additions & 23 deletions src/main/electron/ElectronLauncherApp.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import LauncherApp from '@main/app/LauncherApp';
import { LauncherAppController } from '@main/app/LauncherAppController';
import { BUILTIN_TRUSTED_SITES, CLIENT_ID, IS_DEV } from '@main/constant';
import { client, IS_DEV } from '@main/constant';
import { isDirectory } from '@main/util/fs';
import { UpdateInfo } from '@universal/entities/update';
import { StaticStore } from '@universal/util/staticStore';
import { Task } from '@xmcl/task';
import { app, BrowserWindow, ipcMain, shell } from 'electron';
import { autoUpdater } from 'electron-updater';
import { createServer } from 'http';
import { join } from 'path';
import { parse } from 'url';
import Controller from './Controller';
Expand All @@ -30,8 +31,8 @@ export default class ElectronLauncherApp extends LauncherApp {

exit = app.exit;

getPath(key: string) {
return app.getPath(key as any);
getPath(key: 'home' | 'appData' | 'userData' | 'cache' | 'temp' | 'exe' | 'module' | 'desktop' | 'documents' | 'downloads' | 'music' | 'pictures' | 'videos' | 'logs' | 'pepperFlashSystemPlugin') {
return app.getPath(key);
}

handle = ipcMain.handle;
Expand Down Expand Up @@ -145,18 +146,32 @@ export default class ElectronLauncherApp extends LauncherApp {
}
}

if (IS_DEV) {
const server = createServer((message, response) => {
this.log(`Dev server recieve ${message.url}`);
this.handleUrl(message.url!);
response.statusCode = 200;
response.end();
});
server.listen(3000, () => {
this.log('Started development server!');
});
}

// forward window-all-closed event
app.on('window-all-closed', () => {
this.emit('window-all-closed');
});

app.on('open-url', (event, url) => {
event.preventDefault();
this.log(`open-url ${url}`);
this.handleUrl(url);
}).on('second-instance', (e, argv) => {
this.log(`second-instance ${JSON.stringify(argv)}`);
if (process.platform === 'win32') {
this.log(`second-instance ${JSON.stringify(argv)}`);
const last = argv[argv.length - 1];
if (last.startsWith('xmcl://')) {
this.handleUrl(last);
}
// Keep only command line / deep linked arguments
// this.startFromFilePath(argv[argv.length - 1]);
}
Expand All @@ -169,27 +184,20 @@ export default class ElectronLauncherApp extends LauncherApp {
return app.getLocale();
}

async gainMicrosoftAuthCode(): Promise<string> {
await shell.openExternal(`https://login.live.com/oauth20_authorize.srf?client_id=${CLIENT_ID}&response_type=code&redirect_uri=xmcl://auth&scope=XboxLive.signin`);
return new Promise<string>((resolve) => {
this.once('microsoft-authorize-code', resolve);
});
handleUrl(url: string) {
const parsed = parse(url, true);
if ((parsed.host === 'launcher' || IS_DEV) && parsed.pathname === '/auth') {
let error: Error | undefined;
if (parsed.query.error) {
error = new Error(unescape(parsed.query.error_description as string));
(error as any).error = parsed.query.error;
}
this.emit('microsoft-authorize-code', error, parsed.query.code as string);
}
}

protected async onEngineReady() {
app.allowRendererProcessReuse = true;
app.on('open-url', (event, url) => {
const parsed = parse(url, true);
if (parsed.protocol === 'xmcl:') {
switch (parsed.host) {
case 'auth':
this.emit('microsoft-authorize-code', parsed.query.code as string);
break;
default:
break;
}
}
});
return super.onEngineReady();
}

Expand Down
Loading

0 comments on commit 410540d

Please sign in to comment.