mirror of
https://github.com/HeyPuter/puter.git
synced 2026-10-15 00:00:04 +00:00
Signing up from a direct /app/<name> landing redirected to '/' on success, silently dropping the app the URL asked for — the deep link's launch (and its dashboard intro) never happened. Signup now mirrors login's pathname-preserving redirect, but only for app-landing routes (/app/<name>, /desktop/app/<name>): every other route keeps the historical '/', notably /action/signup, where returning to the same path would just show the signup form again. The query string stays dropped, matching login's credential-leak hygiene. This covers all three signup entry points reachable from a landing: the login cover's "Sign up", the session picker's "Create Account", and the must_login_or_signup fallback. The session picker (UIWindowSessionList) also left itself on top of the cover windows its two links open, hiding their username fields: "Create Account" tried to close the picker via the LOGIN window's c2a selector (which matches nothing in the picker), and "Log Into Another Account" never closed it at all. Both now close the picker — in the reload flows only: the no-reload (popup) flows keep it open, where it doubles as the fallback UI when the login/signup window is abandoned mid-flow. Picking an account was already correct (location.reload() keeps the landing URL); with these fixes all three picker paths, plain login, and signup all return to the app landing, where the boot replays the launch and its intro.
186 lines
8.1 KiB
JavaScript
186 lines
8.1 KiB
JavaScript
/*
|
|
* Copyright (C) 2024-present Puter Technologies Inc.
|
|
*
|
|
* This file is part of Puter.
|
|
*
|
|
* Puter is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published
|
|
* by the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import UIWindow from './UIWindow.js';
|
|
import UIWindowLogin from './UIWindowLogin.js';
|
|
import UIWindowSignup from './UIWindowSignup.js';
|
|
|
|
async function UIWindowSessionList (options) {
|
|
options = options ?? {};
|
|
options.reload_on_success = options.reload_on_success ?? true;
|
|
|
|
return new Promise(async (resolve) => {
|
|
let h = '';
|
|
h += '<div style="margin:10px;">';
|
|
// loading indicator with spinner
|
|
h += `<div class="loading" style="z-index: 999999999;">
|
|
<div style="display: flex; flex-direction: column; align-items: center; gap: 15px;">
|
|
<div style="
|
|
width: 40px;
|
|
height: 40px;
|
|
border: 3px solid #e0e0e0;
|
|
border-top-color: #3b82f6;
|
|
border-radius: 50%;
|
|
animation: spin 0.8s linear infinite;
|
|
"></div>
|
|
<div style="
|
|
font-size: 15px;
|
|
color: #555;
|
|
font-weight: 500;
|
|
">${i18n('signing_in')}</div>
|
|
</div>
|
|
</div>`;
|
|
// session list
|
|
h += '<div class="hide-scrollbar" style="overflow-y: scroll; max-width: 400px; margin: 0 auto;">';
|
|
h += `<h1 style="text-align: center; font-size: 18px; font-weight: normal; color: #757575; margin-bottom: 30px;"><img src="${window.icons['logo-white.svg']}" style="padding: 4px; background-color: blue; border-radius: 5px; width: 25px; box-sizing: border-box; margin-bottom: -6px; margin-right: 6px;">${i18n('sign_in_with_puter')}</h1>`;
|
|
for ( let index = 0; index < window.logged_in_users.length; index++ ) {
|
|
const l_user = window.logged_in_users[index];
|
|
h += `<div data-uuid="${l_user.uuid}" class="session-entry" style="display: flex; padding: 15px 10px;">`;
|
|
// profile picture
|
|
h += `<div class="profile-picture" style="background-color: #cbced1; width: 30px; height: 30px; margin:0; margin-right: 10px; background-image: url('${l_user.profile.picture ?? window.icons['profile.svg']}');"></div>`;
|
|
h += `<div style="display: flex; align-items: center;">${l_user.username}</div>`;
|
|
h += '</div>';
|
|
}
|
|
h += '</div>';
|
|
// c2a
|
|
h += `<div style="margin-top: 20px; margin-bottom: 20px; text-align:center;"><span class="login-c2a-session-list">Log Into Another Account</span> • <span class="signup-c2a-session-list">${i18n('create_account')}</span></div>`;
|
|
h += '</div>';
|
|
|
|
const el_window = await UIWindow({
|
|
title: i18n('window_title_session_list'),
|
|
app: 'session-list',
|
|
single_instance: true,
|
|
icon: null,
|
|
uid: null,
|
|
is_dir: false,
|
|
body_content: h,
|
|
has_head: false,
|
|
selectable_body: false,
|
|
draggable_body: options.draggable_body ?? true,
|
|
allow_context_menu: false,
|
|
is_resizable: false,
|
|
is_droppable: false,
|
|
init_center: true,
|
|
allow_native_ctxmenu: false,
|
|
allow_user_select: false,
|
|
width: 350,
|
|
height: 'auto',
|
|
dominant: true,
|
|
show_in_taskbar: false,
|
|
update_window_url: false,
|
|
cover_page: options.cover_page ?? false,
|
|
window_class: 'window-session-list',
|
|
body_css: {
|
|
width: 'initial',
|
|
height: '100%',
|
|
'background-color': 'rgb(245 247 249)',
|
|
'backdrop-filter': 'blur(3px)',
|
|
'display': 'flex',
|
|
'flex-direction': 'column',
|
|
'justify-content': 'center',
|
|
},
|
|
});
|
|
$(el_window).find('.login-c2a-session-list').on('click', async function (e) {
|
|
// The login window is a centered cover and this picker would
|
|
// otherwise float on top of it, hiding its username field. Only
|
|
// the reload flows close it: in the no-reload (popup) flows the
|
|
// picker doubles as the fallback UI when the login window is
|
|
// abandoned, and the resolve() below still needs a live promise
|
|
// chain either way.
|
|
if ( options.reload_on_success ) $(el_window).close();
|
|
const login = await UIWindowLogin({
|
|
referrer: options.referrer,
|
|
reload_on_success: options.reload_on_success,
|
|
cover_page: options.cover_page ?? false,
|
|
has_head: options.has_head,
|
|
send_confirmation_code: options.send_confirmation_code,
|
|
window_options: {
|
|
has_head: false,
|
|
cover_page: options.cover_page ?? false,
|
|
},
|
|
});
|
|
if ( login ) {
|
|
if ( options.reload_on_success ) {
|
|
// disable native browser exit confirmation
|
|
window.onbeforeunload = null;
|
|
// refresh
|
|
location.reload();
|
|
} else {
|
|
resolve(login);
|
|
}
|
|
}
|
|
});
|
|
$(el_window).find('.signup-c2a-session-list').on('click', async function (e) {
|
|
// Same picker-over-cover overlap as the login c2a above, same
|
|
// reload-flows-only close. (The selector this replaces —
|
|
// '.signup-c2a-clickable', the LOGIN window's c2a class —
|
|
// matched nothing in this window and closed nothing.)
|
|
if ( options.reload_on_success ) $(el_window).close();
|
|
// create Signup window
|
|
const signup = await UIWindowSignup({
|
|
referrer: options.referrer,
|
|
reload_on_success: options.reload_on_success,
|
|
send_confirmation_code: options.send_confirmation_code,
|
|
window_options: {
|
|
has_head: false,
|
|
cover_page: options.cover_page ?? false,
|
|
},
|
|
|
|
});
|
|
if ( signup ) {
|
|
if ( options.reload_on_success ) {
|
|
// disable native browser exit confirmation
|
|
window.onbeforeunload = null;
|
|
// refresh
|
|
location.reload();
|
|
} else {
|
|
resolve(signup);
|
|
}
|
|
}
|
|
});
|
|
|
|
$(el_window).find('.session-entry').on('click', function (e) {
|
|
$(el_window).find('.loading').css({ display: 'flex' });
|
|
|
|
setTimeout(async () => {
|
|
let selected_uuid = $(this).attr('data-uuid');
|
|
let selected_user;
|
|
for ( let index = 0; index < window.logged_in_users.length; index++ ) {
|
|
const l_user = window.logged_in_users[index];
|
|
if ( l_user.uuid === selected_uuid ) {
|
|
selected_user = l_user;
|
|
}
|
|
}
|
|
|
|
// new logged in user
|
|
await window.update_auth_data(selected_user.auth_token, selected_user);
|
|
if ( options.reload_on_success ) {
|
|
// disable native browser exit confirmation
|
|
window.onbeforeunload = null;
|
|
// refresh
|
|
location.reload();
|
|
} else {
|
|
resolve(true);
|
|
}
|
|
}, 500);
|
|
});
|
|
});
|
|
}
|
|
|
|
export default UIWindowSessionList; |