feat(mobile): connect Android and IDE to browser account login

This commit is contained in:
yilsem committed 2026-09-08 21:10:49 +03:00
1 parent b66daed07a
commit c1929957a2
8 files changed
+109 -8

No files matched your search

+3
View File
@@ -2,6 +2,9 @@ import { completeIce, rtcConfiguration, sendFrame } from './mobile/transport.mjs
const host = window.mobileHost, $ = id => document.getElementById(id), peers = new Map()
const status = text => { $('status').textContent = text }
function action(id, work) { $(id).onclick = async () => { $(id).disabled = true; try { await work() } catch (error) { status(error.message) } finally { $(id).disabled = false } } }
action('login-start', async () => { const result = await host.call('account.login.start'); $('login-code').textContent = `Açılan hesap sayfasında yalnız bu kodu onaylayın: ${result.code}` })
action('login-check', async () => { const result = await host.call('account.login.check'); status(result.approved ? 'Hesaba giriş yapıldı. Bu bilgisayarı eşleştirebilirsiniz.' : 'Tarayıcıdaki kod onayı bekleniyor.') })
action('logout', async () => { await host.call('account.logout'); listening = false; $('login-code').textContent = ''; status('Mobil oturum kapatıldı; hesap ve Google anahtarı bu bilgisayar kasasından temizlendi.') })
action('save', async () => { const token = $('account').value; $('account').value = ''; await host.call('account.save', { token }); status('Hesap anahtarı Windows kasasına kaydedildi.') })
action('pair', async () => { const pair = await host.call('desktop.pair'); $('code').textContent = `Açılan hesap sayfasında bu kodu onaylayın: ${pair.code}. Süre: ${pair.expiresAt}` })
action('approve', async () => { await host.call('phone.approve', { pairingId: $('pairing').value.trim(), code: $('phone-code').value.trim().toUpperCase() }); $('phone-code').value = ''; status('Telefon bu bilgisayarda onaylandı.') })
+5 -1
View File
@@ -4,8 +4,12 @@
<p class="eyebrow">AITURK · BİLGİSAYAR</p><h1>Telefonunu bağla.</h1>
<p>Bu pencere açıkken eşleştirdiğiniz Android telefon seçtiğiniz IDE konuşmasına erişebilir. Google anahtarı Windows güvenli kasasında tutulur.</p>
<p id="status" role="status" aria-live="polite">Bağlantı kapalı.</p>
<button id="login-start">AITURK hesabımla giriş yap</button><p id="login-code"></p><button id="login-check">Girişi kontrol et</button>
<p>Çıkış, mobil bağlantıları kapatır ve bu penceredeki hesap/Google anahtarını Windows kasasından temizler; başlamış IDE işini durdurmaz.</p>
<button id="logout">Mobil oturumdan çık ve kasayı temizle</button>
<details><summary>Gelişmiş: hesap API anahtarı</summary>
<label>AITURK hesap API anahtarı<input id="account" type="password" autocomplete="off"></label>
<button id="save">Hesap anahtarını kaydet</button><button id="pair">Bu bilgisayarı hesabımla eşleştir</button>
<button id="save">Hesap anahtarını kaydet</button></details><button id="pair">Bu bilgisayarı hesabımla eşleştir</button>
<p id="code"></p><hr>
<h2>Telefona izin ver</h2><p>Telefondaki eşleştirme kimliğini ve 8 karakterli kodu buraya girin. Bu onay yalnız bu telefon ile bu bilgisayarı bağlar.</p>
<label>Eşleştirme kimliği<input id="pairing"></label><label>Telefondaki kod<input id="phone-code" maxlength="8" autocapitalize="characters"></label>
+25
View File
@@ -33,6 +33,31 @@ export function createMobileWindow({ directory, assets, resolveBackend, show = t
await vault.save({ ...previous, accountToken: params.token })
return { saved: true }
}
if (action === 'account.login.start') {
const previous = await vault.load()
if (previous.accountToken || clients.size) throw new Error('Kayıtlı hesap var. Önce mevcut cihazı iptal edin.')
const login = await new AccountClient({}).call('/v1/aiturk/mobile-auth/start', {})
if (!/^https:\/\/turkservis\.online\/account\/aiturk\/mobile-login\/[0-9a-f-]{36}$/.test(login.verificationUri)) throw new Error('Geçersiz giriş adresi.')
await vault.save({ ...previous, pendingLogin: login })
await shell.openExternal(login.verificationUri)
return { code: login.userCode }
}
if (action === 'account.login.check') {
const previous = await vault.load()
if (!previous.pendingLogin) throw new Error('Önce giriş başlatın.')
const result = await new AccountClient({ accountToken: previous.pendingLogin.deviceCode }).call('/v1/aiturk/mobile-auth/poll', {})
if (result.state !== 'approved') return { approved: false }
delete previous.pendingLogin
await vault.save({ ...previous, accountToken: result.accountToken })
return { approved: true }
}
if (action === 'account.logout') {
const previous = await vault.load(), token = previous.accountToken || previous.pendingLogin?.deviceCode
if (token?.startsWith('tsml_')) await new AccountClient({ accountToken: token }).call('/v1/aiturk/mobile-auth/logout', {})
for (const [id, entry] of clients) { entry.client.close(); send({ channelId: id, close: true }) }
clients.clear(); await vault.save({})
return { cleared: true }
}
if (action === 'desktop.pair') {
const result = await call('/v1/aiturk/pairings', { display_name: hostname(), platform: 'windows-x64' })
await vault.save({ ...await vault.load(), deviceId: result.device_id, deviceToken: result.device_token,