diff --git a/src/UI/Components/Flexer.js b/src/UI/Components/Flexer.js
index dd53a34f..47b9b46c 100644
--- a/src/UI/Components/Flexer.js
+++ b/src/UI/Components/Flexer.js
@@ -7,22 +7,36 @@ import { Component } from "../../util/Component.js";
export default class Flexer extends Component {
static PROPERTIES = {
children: {},
+ gap: { value: '20pt' },
}
+ static CSS = `
+ :host > div {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+ `;
+
create_template ({ template }) {
// TODO: The way we handle loading assets doesn't work well
// with web components, so for now it goes in the template.
$(template).html(`
-
+
`);
}
- on_ready () {
+ on_ready ({ listen }) {
console.log('Flexer on_ready called');
for ( const child of this.get('children') ) {
child.setAttribute('slot', 'inside');
child.attach(this);
}
+
+ listen('gap', gap => {
+ console.log('gap called', gap);
+ $(this.dom_).find('div').first().css('gap', gap);
+ });
}
}
diff --git a/src/UI/Components/StepHeading.js b/src/UI/Components/StepHeading.js
new file mode 100644
index 00000000..93ac6478
--- /dev/null
+++ b/src/UI/Components/StepHeading.js
@@ -0,0 +1,66 @@
+import { Component } from "../../util/Component.js";
+
+/**
+ * StepHeading renders a heading with a leading symbol.
+ * The leading symbol is styled inside a cricle and is
+ * optimized for single-digit numbers.
+ */
+export default class StepHeading extends Component {
+ static PROPERTIES = {
+ symbol: {
+ description: 'The symbol to display',
+ value: '1',
+ },
+ text: {
+ description: 'The heading to display',
+ value: 'Heading',
+ },
+ }
+
+ static CSS = /*css*/`
+ .heading {
+ display: flex;
+ align-items: center;
+ }
+
+ .circle {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ background-color: #3e5362;
+ color: #FFFFFF;
+ font-size: 20px;
+ font-weight: 700;
+ }
+
+ .text {
+ margin-left: 20px;
+ font-size: 30px;
+ color: hsl(220, 25%, 31%);
+ }
+ `
+
+ create_template ({ template }) {
+ $(template).html(/*html*/`
+
+
+ ${html_encode(this.get('symbol'))}
+
+
+ ${html_encode(this.get('text'))}
+
+
+ `);
+ }
+}
+
+// TODO: This is necessary because files can be loaded from
+// both `/src/UI` and `/UI` in the URL; we need to fix that
+if ( ! window.__component_stepHeading ) {
+ window.__component_stepHeading = true;
+
+ customElements.define('c-step-heading', StepHeading);
+}
diff --git a/src/UI/Components/StringView.js b/src/UI/Components/StringView.js
new file mode 100644
index 00000000..70ec350a
--- /dev/null
+++ b/src/UI/Components/StringView.js
@@ -0,0 +1,46 @@
+import { Component } from "../../util/Component.js";
+
+/**
+ * A simple component that displays a string in the
+ * specified style.
+ */
+export default class StringView extends Component {
+ static PROPERTIES = {
+ text: { value: '' },
+ heading: { value: 0 },
+ }
+
+ static CSS = /*css*/`
+ h2 {
+ margin: 0;
+ color: hsl(220, 25%, 31%);
+ }
+ `;
+
+ create_template ({ template }) {
+ $(template).html(``);
+ }
+
+ on_ready ({ listen }) {
+ // TODO: listener composition, to avoid this
+ const either = ({ heading, text }) => {
+ console.log('---', { heading, text });
+ const wrapper_nodeName = heading ? 'h' + heading : 'span';
+ $(this.dom_).find('span').html(`<${wrapper_nodeName}>${html_encode(text)}${wrapper_nodeName}>`);
+ };
+ listen('heading', heading => {
+ either({ heading, text: this.get('text') });
+ });
+ listen('text', text => {
+ either({ heading: this.get('heading'), text });
+ });
+ }
+}
+
+// TODO: This is necessary because files can be loaded from
+// both `/src/UI` and `/UI` in the URL; we need to fix that
+if ( ! window.__component_stringView ) {
+ window.__component_stringView = true;
+
+ customElements.define('c-string-view', StringView);
+}
diff --git a/src/UI/UIComponentWindow.js b/src/UI/UIComponentWindow.js
index 93d41e01..100dc863 100644
--- a/src/UI/UIComponentWindow.js
+++ b/src/UI/UIComponentWindow.js
@@ -14,38 +14,10 @@ export default async function UIComponentWindow (options) {
const placeholder = Placeholder();
await UIWindow({
- title: 'Instant Login!',
- app: 'instant-login',
- single_instance: true,
- icon: null,
- uid: null,
- is_dir: false,
+ ...options,
+
body_content: placeholder.html,
- has_head: false,
- selectable_body: false,
- allow_context_menu: false,
- is_resizable: false,
- is_droppable: false,
- init_center: true,
- allow_native_ctxmenu: false,
- allow_user_select: false,
- backdrop: true,
- width: 550,
- height: 'auto',
- dominant: true,
- show_in_taskbar: false,
- draggable_body: true,
- onAppend: function(this_window){
- },
- window_class: 'window-qr',
- body_css: {
- width: 'initial',
- height: '100%',
- 'background-color': 'rgb(245 247 249)',
- 'backdrop-filter': 'blur(3px)',
- padding: '20px',
- },
- })
+ });
options.component.attach(placeholder);
options.component.focus();
diff --git a/src/UI/UIWindow.js b/src/UI/UIWindow.js
index ed182a55..ac86fe00 100644
--- a/src/UI/UIWindow.js
+++ b/src/UI/UIWindow.js
@@ -477,6 +477,9 @@ async function UIWindow(options) {
const el_openfiledialog_open_btn = document.querySelector(`#window-${win_id} .openfiledialog-open-btn`);
const el_directorypicker_select_btn = document.querySelector(`#window-${win_id} .directorypicker-select-btn`);
+ // attach optional event listeners
+ el_window.on_before_exit = options.on_before_exit;
+
// disable menubar by default
$(el_window).find('.window-menubar').hide();
@@ -2813,6 +2816,12 @@ $.fn.close = async function(options) {
}
}
+ console.log('deos ')
+ if ( this.on_before_exit ) {
+ console.log('this happens??');
+ if ( ! await this.on_before_exit() ) return false;
+ }
+
// Process window close if this is a window
if($(this).hasClass('window')){
const win_id = parseInt($(this).attr('data-id'));
diff --git a/src/UI/UIWindow2FASetup.js b/src/UI/UIWindow2FASetup.js
index 0ff378b7..ce5c9dee 100644
--- a/src/UI/UIWindow2FASetup.js
+++ b/src/UI/UIWindow2FASetup.js
@@ -23,8 +23,11 @@ import CodeEntryView from "./Components/CodeEntryView.js";
import Flexer from "./Components/Flexer.js";
import QRCodeView from "./Components/QRCode.js";
import RecoveryCodesView from "./Components/RecoveryCodesView.js";
+import StepHeading from "./Components/StepHeading.js";
import StepView from "./Components/StepView.js";
+import StringView from "./Components/StringView.js";
import TestView from "./Components/TestView.js";
+import UIAlert from "./UIAlert.js";
import UIComponentWindow from "./UIComponentWindow.js";
const UIWindow2FASetup = async function UIWindow2FASetup () {
@@ -63,9 +66,24 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
children: [
new Flexer({
children: [
+ new StepHeading({
+ symbol: '1',
+ text: 'Open Authenticator App',
+ }),
+ new StringView({
+ text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ornare augue eu est pharetra, non faucibus eros finibus. Morbi metus sapien, pretium consequat erat eu, accumsan imperdiet metus. Donec varius libero tellus, malesuada rhoncus nunc viverra eget. Quisque ultrices scelerisque ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non purus varius, molestie nibh vitae, elementum urna. Suspendisse ultricies porta gravida. Nulla eu consequat mi, id mattis leo.',
+ }),
+ new StepHeading({
+ symbol: '2',
+ text: 'Scan This QR Code',
+ }),
new QRCodeView({
value: data.url,
}),
+ new StepHeading({
+ symbol: '3',
+ text: 'Enter Verification Code',
+ }),
new CodeEntryView({
_ref: me => code_entry = me,
async [`property.value`] (value, { component }) {
@@ -86,9 +104,20 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
}),
new Flexer({
children: [
+ new StepHeading({
+ symbol: '4',
+ text: 'Copy Recovery Codes',
+ }),
+ new StringView({
+ text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ornare augue eu est pharetra, non faucibus eros finibus. Morbi metus sapien, pretium consequat erat eu, accumsan imperdiet metus. Donec varius libero tellus, malesuada rhoncus nunc viverra eget. Quisque ultrices scelerisque ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non purus varius, molestie nibh vitae, elementum urna. Suspendisse ultricies porta gravida. Nulla eu consequat mi, id mattis leo.',
+ }),
new RecoveryCodesView({
values: data.codes,
}),
+ new StepHeading({
+ symbol: '5',
+ text: 'Confirm Recovery Codes',
+ }),
]
}),
]
@@ -97,6 +126,55 @@ const UIWindow2FASetup = async function UIWindow2FASetup () {
UIComponentWindow({
component,
+ on_before_exit: async () => {
+ console.log('this was called?');
+ return await UIAlert({
+ message: i18n('cancel_2fa_setup'),
+ buttons: [
+ {
+ label: i18n('yes'),
+ value: true,
+ type: 'primary',
+ },
+ {
+ label: i18n('no'),
+ value: false,
+ },
+ ]
+ });
+ },
+
+ title: 'Instant Login!',
+ app: 'instant-login',
+ single_instance: true,
+ icon: null,
+ uid: null,
+ is_dir: false,
+ // has_head: false,
+ selectable_body: true,
+ // selectable_body: false,
+ allow_context_menu: false,
+ is_resizable: false,
+ is_droppable: false,
+ init_center: true,
+ allow_native_ctxmenu: false,
+ allow_user_select: false,
+ // backdrop: true,
+ width: 550,
+ height: 'auto',
+ dominant: true,
+ show_in_taskbar: false,
+ draggable_body: true,
+ onAppend: function(this_window){
+ },
+ window_class: 'window-qr',
+ body_css: {
+ width: 'initial',
+ height: '100%',
+ 'background-color': 'rgb(245 247 249)',
+ 'backdrop-filter': 'blur(3px)',
+ padding: '20px',
+ },
});
}
diff --git a/src/initgui.js b/src/initgui.js
index c45a427f..f3522541 100644
--- a/src/initgui.js
+++ b/src/initgui.js
@@ -39,6 +39,7 @@ import { BroadcastService } from './services/BroadcastService.js';
import { ProcessService } from './services/ProcessService.js';
import { PROCESS_RUNNING } from './definitions.js';
import { LocaleService } from './services/LocaleService.js';
+import UIWindow2FASetup from './UI/UIWindow2FASetup.js';
const launch_services = async function () {
const services_l_ = [];
@@ -66,6 +67,10 @@ const launch_services = async function () {
const svc_process = globalThis.services.get('process');
svc_process.get_init().chstatus(PROCESS_RUNNING);
}
+
+ setTimeout(() => {
+ UIWindow2FASetup();
+ }, 1000);
};
// This code snippet addresses the issue flagged by Lighthouse regarding the use of
diff --git a/src/util/Component.js b/src/util/Component.js
index 5ef71472..18dd84eb 100644
--- a/src/util/Component.js
+++ b/src/util/Component.js
@@ -4,6 +4,10 @@ export class Component extends HTMLElement {
// Render modes
static NO_SHADOW = Symbol('no-shadow');
+ static TODO = [
+ 'value bindings for create_template',
+ ]
+
constructor (property_values) {
super();