Settings > T5DE gets a T5DE Hub section to sign in (showing the code and opening the hub's page) or out, through T5DE's proxy, which keeps the sign-in. Co-Authored-By: Claude Opus 5.5 <[email protected]>
162 lines
6.9 KiB
Diff
162 lines
6.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: dhkatz <[email protected]>
|
|
Date: Thu, 29 Oct 2026 19:20:16 -0700
|
|
Subject: [PATCH] Sign in to T5DE's hub from Settings
|
|
|
|
Settings > T5DE gets a T5DE Hub section: sign in (it shows a code and opens the hub's page for it in the
|
|
browser) or out, and who's signed in. T5DE's proxy keeps the sign-in and answers the page at
|
|
http://t5de-proxy.local/; signing in or out takes effect at once.
|
|
|
|
Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
|
T5de-Id: t5de-hub
|
|
T5de-Name: T5DE Hub
|
|
T5de-Group: general
|
|
T5de-Depends: t5de-proxy, t5de-renderer
|
|
---
|
|
imvuContent/settings/index.html | 12 ++++++++
|
|
imvuContent/settings/style.css | 9 ++++++
|
|
imvuContent/settings/t5de-hub.js | 47 +++++++++++++++++++++++++++++++
|
|
library/imvu/mode/SettingsMode.py | 20 +++++++++++++
|
|
4 files changed, 88 insertions(+)
|
|
create mode 100644 imvuContent/settings/t5de-hub.js
|
|
|
|
diff --git a/imvuContent/settings/index.html b/imvuContent/settings/index.html
|
|
index 72afd50a1c2ac86ced5d3df19db690df0e82bad4..045ac3e815fcc62e987b119003f7009d7c680ed0 100644
|
|
--- a/imvuContent/settings/index.html
|
|
+++ b/imvuContent/settings/index.html
|
|
@@ -29,6 +29,7 @@
|
|
<script src="BlockActionSettings.js"></script>
|
|
<script src="t5de.js"></script>
|
|
<script src="t5de-graphics.js"></script>
|
|
+ <script src="t5de-hub.js"></script>
|
|
|
|
<script src="../widgets/button/imvuButton.js"></script>
|
|
</head><body class="yui-skin-sam">
|
|
@@ -121,6 +122,16 @@
|
|
</div>
|
|
</div>
|
|
<div class="page" imvu:page="t5de" id="t5de-page">
|
|
+ <div class="subsection" id="t5de-hub">
|
|
+ <h1>T5DE Hub</h1>
|
|
+ <div id="t5de-hub-status"> </div>
|
|
+ <div id="t5de-hub-code" class="hidden"></div>
|
|
+ <div class="t5de-hub-buttons">
|
|
+ <button id="t5de-hub-signin">Sign In</button>
|
|
+ <button id="t5de-hub-signout" class="hidden">Sign Out</button>
|
|
+ </div>
|
|
+ <div class="info t5de-info">Your T5DE account: community products, your library, and who's online.</div>
|
|
+ </div>
|
|
<div class="subsection" id="t5de-graphics">
|
|
<h1>Graphics</h1>
|
|
<div><span class="choice_desc">Frame Rate</span>
|
|
@@ -249,6 +260,7 @@
|
|
var tb = new ToolBar(imvu.call);
|
|
t5deSettings(imvu);
|
|
t5deGraphicsSettings(imvu);
|
|
+ t5deHubSettings(imvu);
|
|
}
|
|
</script>
|
|
</body></html>
|
|
\ No newline at end of file
|
|
diff --git a/imvuContent/settings/style.css b/imvuContent/settings/style.css
|
|
index 76187e882716ca5bcccf71952ba8657a739495c0..c846b5ef0772ff8b8fb5e1643bc45b55285bb984 100644
|
|
--- a/imvuContent/settings/style.css
|
|
+++ b/imvuContent/settings/style.css
|
|
@@ -480,3 +480,12 @@ ul li {
|
|
.t5de-info {
|
|
margin-top: 10px;
|
|
}
|
|
+#t5de-hub-code {
|
|
+ margin-top: 6px;
|
|
+ font-size: 16px;
|
|
+ font-weight: bold;
|
|
+ letter-spacing: 2px;
|
|
+}
|
|
+.t5de-hub-buttons {
|
|
+ margin-top: 8px;
|
|
+}
|
|
diff --git a/imvuContent/settings/t5de-hub.js b/imvuContent/settings/t5de-hub.js
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..2cb97c2d76e8429a3cd36372a34e28324a731137
|
|
--- /dev/null
|
|
+++ b/imvuContent/settings/t5de-hub.js
|
|
@@ -0,0 +1,47 @@
|
|
+// Signing in to T5DE's hub (the T5DE Hub patch), through T5DE's proxy, which keeps the sign-in
|
|
+// (SettingsMode.py: handle_t5deHub). Signing in opens the hub's page in the browser for the code shown here.
|
|
+function t5deHubSettings(imvu) {
|
|
+ var status = document.getElementById('t5de-hub-status');
|
|
+ var code = document.getElementById('t5de-hub-code');
|
|
+ var signin = document.getElementById('t5de-hub-signin');
|
|
+ var signout = document.getElementById('t5de-hub-signout');
|
|
+ var timer = null;
|
|
+
|
|
+ function call(action) {
|
|
+ try {
|
|
+ return JSON.parse(imvu.call('t5deHub', action));
|
|
+ } catch (e) {
|
|
+ return {error: 'proxy'};
|
|
+ }
|
|
+ }
|
|
+
|
|
+ function show(s) {
|
|
+ $(code).addClass('hidden');
|
|
+ $(signin).toggleClass('hidden', !!s.signedIn);
|
|
+ $(signout).toggleClass('hidden', !s.signedIn);
|
|
+ if (s.error === 'proxy') {
|
|
+ status.textContent = "T5DE's proxy isn't running.";
|
|
+ $(signin).addClass('hidden');
|
|
+ } else if (s.signedIn) {
|
|
+ status.textContent = s.username ? 'Signed in as ' + s.username + '.' : 'Signed in.';
|
|
+ } else if (s.signingIn) {
|
|
+ status.textContent = s.code ? 'Enter this code on the page that opened:' : 'Getting a code...';
|
|
+ if (s.code) {
|
|
+ code.textContent = s.code.slice(0, 4) + '-' + s.code.slice(4);
|
|
+ $(code).removeClass('hidden');
|
|
+ }
|
|
+ } else if (s.error) {
|
|
+ status.textContent = "Couldn't sign in: " + s.error;
|
|
+ } else {
|
|
+ status.textContent = 'Not signed in.';
|
|
+ }
|
|
+ clearTimeout(timer);
|
|
+ if (s.signingIn || (s.signedIn && !s.username)) {
|
|
+ timer = setTimeout(function () { show(call('status')); }, 1500);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ signin.addEventListener('click', function () { show(call('signin')); }, false);
|
|
+ signout.addEventListener('click', function () { show(call('signout')); }, false);
|
|
+ show(call('status'));
|
|
+}
|
|
diff --git a/library/imvu/mode/SettingsMode.py b/library/imvu/mode/SettingsMode.py
|
|
index 69a1ca1d6ca6ca2818c3d96cdd11c63939243c9f..27ef0499f542c9f7e558d94fcc82b34fdb98f185 100644
|
|
--- a/library/imvu/mode/SettingsMode.py
|
|
+++ b/library/imvu/mode/SettingsMode.py
|
|
@@ -65,6 +65,26 @@ class SettingsGeckoListener(object):
|
|
_winreg.SetValueEx(key, 'FrameRate', 0, _winreg.REG_DWORD, int(rate))
|
|
finally:
|
|
key.Close()
|
|
+
|
|
+ def handle_t5deHub(self, context, action):
|
|
+ """T5DE's hub sign-in, kept by T5DE's proxy, which answers at http://t5de-proxy.local/: action 'status',
|
|
+ 'signin' or 'signout'. The proxy's answer as JSON text, or {"error": "proxy"} if it isn't running."""
|
|
+ import httplib, json
|
|
+ from main.client import t5deProxy, t5deProxyAuthorization
|
|
+ proxy = t5deProxy()
|
|
+ if proxy is None:
|
|
+ return json.dumps({'error': 'proxy'})
|
|
+ host, port, token = proxy
|
|
+ method, path = {'status': ('GET', '/hub'), 'signin': ('POST', '/hub/signin'), 'signout': ('POST', '/hub/signout')}[action]
|
|
+ conn = httplib.HTTPConnection(host, port, timeout=10)
|
|
+ try:
|
|
+ conn.request(method, 'http://t5de-proxy.local' + path, '', {'Proxy-Authorization': t5deProxyAuthorization(token)})
|
|
+ response = conn.getresponse()
|
|
+ return response.read() if response.status == 200 else json.dumps({'error': 'proxy'})
|
|
+ except Exception:
|
|
+ return json.dumps({'error': 'proxy'})
|
|
+ finally:
|
|
+ conn.close()
|
|
def handle_registerSettingsListeners(self, context, prefList):
|
|
for pref in prefList:
|
|
self.__serviceProvider.eventBus.register(self.__serviceProvider.prefService, 'PrefChanged-%s' % (pref,), self.__prefListener)
|