Merge: View and Page enums in place of the six view booleans
This commit is contained in:
@@ -17,7 +17,7 @@ use slint::{ComponentHandle, Model as _, ModelRc, VecModel};
|
||||
|
||||
use crate::faces::FaceSweepMessage;
|
||||
use crate::identity::{self, FaceCell, PersonRow};
|
||||
use crate::{AppWindow, IdentityFace, IdentityPerson};
|
||||
use crate::{AppWindow, IdentityFace, IdentityPerson, View};
|
||||
|
||||
/// Which model's faces the screen is looking at.
|
||||
///
|
||||
@@ -740,14 +740,14 @@ fn wire_navigation(
|
||||
let models_present = models.clone();
|
||||
window.on_identity_open(move || {
|
||||
let Some(w) = weak.upgrade() else { return };
|
||||
let from_library = w.get_show_library();
|
||||
let from_library = w.get_active_view() == View::Library;
|
||||
ctl.came_from_library.set(from_library);
|
||||
w.set_identity_back_label(if from_library {
|
||||
"‹ Library".into()
|
||||
} else {
|
||||
"‹ Develop".into()
|
||||
});
|
||||
w.set_show_identity(true);
|
||||
w.set_active_view(View::Identity);
|
||||
// A fact about the filesystem, so it is re-checked on every open
|
||||
// rather than cached: the user may have just put the models there.
|
||||
w.set_identity_model_missing(models_present().is_none());
|
||||
@@ -768,8 +768,11 @@ fn wire_navigation(
|
||||
// Back to whichever screen this was opened from. The develop
|
||||
// session was never torn down — it was only hidden — so returning
|
||||
// to it costs nothing and keeps the photographer's place.
|
||||
w.set_show_library(ctl.came_from_library.get());
|
||||
w.set_show_identity(false);
|
||||
w.set_active_view(if ctl.came_from_library.get() {
|
||||
View::Library
|
||||
} else {
|
||||
View::Develop
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ use dr_types::{FormatFilter, ImportSettings};
|
||||
|
||||
use crate::activity::{Activity, ActivityLog, Kind};
|
||||
use crate::import::{self, Message, Request, Upload};
|
||||
use crate::AppWindow;
|
||||
use crate::{AppWindow, Page};
|
||||
|
||||
/// How often the drain runs while an import is going.
|
||||
///
|
||||
@@ -344,7 +344,7 @@ where
|
||||
*ctl.error.borrow_mut() = String::new();
|
||||
survey(&w, &ctl, &context);
|
||||
render(&w, &ctl);
|
||||
w.set_show_import(true);
|
||||
w.set_active_page(Page::Import);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ where
|
||||
if ctl.running.get() {
|
||||
return;
|
||||
}
|
||||
w.set_show_import(false);
|
||||
w.set_active_page(Page::None);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use dr_sync_nextcloud::{auth, NextcloudProvider};
|
||||
use slint::ComponentHandle;
|
||||
|
||||
use crate::launch::{LaunchModel, LaunchState};
|
||||
use crate::AppWindow;
|
||||
use crate::{AppWindow, View};
|
||||
|
||||
/// Shared launch state for the running window.
|
||||
pub struct LaunchController {
|
||||
@@ -257,7 +257,7 @@ fn wire_choose_folder_and_open<F>(
|
||||
let Some(w) = weak.upgrade() else { return };
|
||||
let session = ctl.model.borrow().session().cloned();
|
||||
if let Some(s) = session {
|
||||
w.set_show_launch(false);
|
||||
w.set_active_view(View::Library);
|
||||
on_open_library(s);
|
||||
}
|
||||
});
|
||||
|
||||
+26
-4
@@ -1618,7 +1618,13 @@ fn construct_screens(
|
||||
{
|
||||
let controller = launch_ui::LaunchController::new();
|
||||
let startup = controller.model.borrow().startup_action(!paths.is_empty());
|
||||
window.set_show_launch(startup == launch::Startup::ShowLaunchScreen);
|
||||
// `OpenLibrary` is overwritten moments later by `library_ui::open`
|
||||
// below, once a stored session exists; `ShowLocalFiles` leaves
|
||||
// `develop` as it found it, since there is no library to switch to.
|
||||
window.set_active_view(match startup {
|
||||
launch::Startup::ShowLaunchScreen => View::Launch,
|
||||
launch::Startup::ShowLocalFiles | launch::Startup::OpenLibrary => View::Develop,
|
||||
});
|
||||
|
||||
let library = library.clone();
|
||||
let collections = collections.clone();
|
||||
@@ -3404,11 +3410,27 @@ fn apply_layout_class(
|
||||
/// the activity — the behaviour every application there has, and the reason
|
||||
/// this answers with a bool rather than swallowing the gesture.
|
||||
fn back_one_step(w: &AppWindow) -> bool {
|
||||
// The Identity screen has no representation in `NavState`: nothing here
|
||||
// records which view it replaced, only `identity_ui`'s own
|
||||
// `came_from_library`, which this function has no reason to reach for
|
||||
// over one screen. Before this refactor, back queued nothing behind
|
||||
// Identity opened from the library (show-library stayed true, unread by
|
||||
// anything) and queued `ToLibrary` behind Identity opened from develop —
|
||||
// but `ToLibrary` only ever set `show-library`, a property
|
||||
// `IdentityScreen`'s own `if` never read, so both cases looked the same
|
||||
// on screen: nothing happened. Swallowing the gesture here keeps that:
|
||||
// falling into the general case below would instead write `active-view`,
|
||||
// which `IdentityScreen`'s `if` *does* read, and close the screen as a
|
||||
// side effect nobody asked for.
|
||||
if w.get_active_view() == View::Identity {
|
||||
return true;
|
||||
}
|
||||
|
||||
let state = NavState {
|
||||
settings: w.get_show_settings(),
|
||||
launch: w.get_show_launch(),
|
||||
settings: w.get_active_page() == Page::Settings,
|
||||
launch: w.get_active_view() == View::Launch,
|
||||
browsing: w.get_launch_browsing(),
|
||||
library: w.get_show_library(),
|
||||
library: w.get_active_view() == View::Library,
|
||||
mode: w.global::<Develop>().get_view_mode(),
|
||||
zoomed: w.get_zoomed(),
|
||||
// Files named on the command line have no grid behind them — the same
|
||||
|
||||
+14
-14
@@ -22,7 +22,7 @@ use dr_types::FormatFilter;
|
||||
use slint::{ComponentHandle, Model as _};
|
||||
|
||||
use crate::library::{self, ScanMessage, ThumbnailMessage};
|
||||
use crate::{AppWindow, GestureRow, KeywordRow, LibraryCell, PersonChip, TimelineBar};
|
||||
use crate::{AppWindow, GestureRow, KeywordRow, LibraryCell, PersonChip, TimelineBar, View};
|
||||
|
||||
/// A screenful before the grid has reported its geometry.
|
||||
///
|
||||
@@ -957,7 +957,7 @@ pub fn open(
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
window.set_library_error(format!("credentials: {e}").into());
|
||||
window.set_show_library(true);
|
||||
window.set_active_view(View::Library);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -977,7 +977,7 @@ pub fn open(
|
||||
// another device may still be applied — see `place_untouched`.
|
||||
ctl.place_untouched.set(true);
|
||||
|
||||
window.set_show_library(true);
|
||||
window.set_active_view(View::Library);
|
||||
window.set_library_open(true);
|
||||
window.set_library_scanning(true);
|
||||
window.set_library_error(slint::SharedString::new());
|
||||
@@ -5391,7 +5391,7 @@ fn write_place(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
fn current_place(window: &AppWindow, ctl: &Rc<LibraryController>) -> Option<dr_types::Place> {
|
||||
use dr_types::{Place, PlaceScope, Screen};
|
||||
|
||||
if window.get_show_launch() || !window.get_library_open() {
|
||||
if window.get_active_view() == View::Launch || !window.get_library_open() {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -5401,7 +5401,7 @@ fn current_place(window: &AppWindow, ctl: &Rc<LibraryController>) -> Option<dr_t
|
||||
// tracks; in develop it is the open one, which `report_position` keeps
|
||||
// `index` holding. Both are library ordinals against the same ordering, so
|
||||
// the lookup below is one piece of code rather than two.
|
||||
let in_library = window.get_show_library();
|
||||
let in_library = window.get_active_view() == View::Library;
|
||||
let at = if in_library {
|
||||
ctl.resume_at.get()
|
||||
} else {
|
||||
@@ -5544,7 +5544,7 @@ pub(crate) fn apply_place(
|
||||
if place.screen == Screen::Develop {
|
||||
if let Some((at, Found::Photograph)) = resolved {
|
||||
if let Some(open) = ctl.open_image.borrow().clone() {
|
||||
window.set_show_library(false);
|
||||
window.set_active_view(View::Develop);
|
||||
window.set_library_roll_centre(true);
|
||||
let offset = *ctl.offset.borrow();
|
||||
if let Some(row) = at.checked_sub(offset) {
|
||||
@@ -5836,7 +5836,7 @@ pub fn wire<F>(
|
||||
if let Some(path) = path {
|
||||
// Leave the grid for the develop view. The status bar's
|
||||
// "‹ Library" button comes back here.
|
||||
w.set_show_library(false);
|
||||
w.set_active_view(View::Develop);
|
||||
// Which cell the develop view is now showing, so the photo
|
||||
// roll opens marking it rather than marking nothing.
|
||||
w.set_library_roll_current(i);
|
||||
@@ -5940,7 +5940,7 @@ fn wire_grid_cursor_and_zoom(
|
||||
let row = cursor.checked_sub(offset);
|
||||
let path = row.and_then(|row| ctl.paths.borrow().get(row).cloned());
|
||||
if let Some(path) = path {
|
||||
w.set_show_library(false);
|
||||
w.set_active_view(View::Develop);
|
||||
// As on a click: the roll marks what is open, and centres on it
|
||||
// because this too begins a session.
|
||||
w.set_library_roll_current(row.unwrap_or(0) as i32);
|
||||
@@ -6367,7 +6367,7 @@ fn wire_grid_routes(
|
||||
let weak = window.as_weak();
|
||||
window.on_library_change(move || {
|
||||
if let Some(w) = weak.upgrade() {
|
||||
w.set_show_launch(true);
|
||||
w.set_active_view(View::Launch);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -6401,10 +6401,11 @@ fn wire_grid_routes(
|
||||
let open = w.get_index().max(0) as usize;
|
||||
resume_position(&w, &ctl, &coll_ctl, Some(open));
|
||||
|
||||
w.set_show_library(true);
|
||||
w.set_active_view(View::Library);
|
||||
// TRACES: FR-UI-8
|
||||
// After the flag, not before: `current_place` reads it to say which
|
||||
// view the record is of, and this is the moment it becomes the grid.
|
||||
// After the view is set, not before: `current_place` reads it to
|
||||
// say which view the record is of, and this is the moment it
|
||||
// becomes the grid.
|
||||
write_place(&w, &ctl);
|
||||
});
|
||||
}
|
||||
@@ -6640,8 +6641,7 @@ fn wire_filter_ratings_and_people(window: &AppWindow, ctl: &Rc<LibraryController
|
||||
// Leaving the Identity screen for the grid is the whole point of
|
||||
// the button: the answer to "who is this" is a set of photographs,
|
||||
// and they are shown where photographs are shown.
|
||||
w.set_show_identity(false);
|
||||
w.set_show_library(true);
|
||||
w.set_active_view(View::Library);
|
||||
refilter(&w, &ctl);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::merge::{
|
||||
self, AlignmentReport, Cancel, Decision, FillSettings, MergeDestination, MergeEvent,
|
||||
MergeInput, MergeRequest,
|
||||
};
|
||||
use crate::{AppWindow, MergeFrameRow};
|
||||
use crate::{AppWindow, MergeFrameRow, Page};
|
||||
|
||||
/// How often the page reads the job's channel.
|
||||
const DRAIN_INTERVAL: std::time::Duration = std::time::Duration::from_millis(120);
|
||||
@@ -411,7 +411,7 @@ fn wire_stop_and_leave(window: &AppWindow, ctl: &Rc<MergeController>) {
|
||||
job.activity.finish_quietly();
|
||||
}
|
||||
*ctl.timer.borrow_mut() = None;
|
||||
w.set_show_merge(false);
|
||||
w.set_active_page(Page::None);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -481,7 +481,7 @@ fn start<Fetch>(
|
||||
window.set_merge_fill_note("".into());
|
||||
window.set_merge_preview_filled(false);
|
||||
window.set_merge_done(false);
|
||||
window.set_show_merge(true);
|
||||
window.set_active_page(Page::Merge);
|
||||
|
||||
let timer = slint::Timer::default();
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ use dr_types::{
|
||||
use slint::ComponentHandle;
|
||||
|
||||
use crate::settings_store::SettingsStore;
|
||||
use crate::{Adjustments, AppWindow};
|
||||
use crate::{Adjustments, AppWindow, Page};
|
||||
use dr_sync::Connection;
|
||||
|
||||
/// Shared settings state for the running window.
|
||||
@@ -436,7 +436,7 @@ fn wire_open_close(
|
||||
*ctl.settings.borrow_mut() = ctl.store.load();
|
||||
render(&w, &ctl);
|
||||
on_open(&w);
|
||||
w.set_show_settings(true);
|
||||
w.set_active_page(Page::Settings);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ fn wire_open_close(
|
||||
let weak = window.as_weak();
|
||||
window.on_settings_close(move || {
|
||||
let Some(w) = weak.upgrade() else { return };
|
||||
w.set_show_settings(false);
|
||||
w.set_active_page(Page::None);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+65
-26
@@ -32,6 +32,45 @@ export { ViewMode, GradientHandle, HandleRole, SpotHandle, SpotRole }
|
||||
// panels take their wiring this way and why there is one global per family.
|
||||
export { Develop, Capture, Levels, Peaking, Adjustments, Framing, Transfer, Masking, Repair, Steps }
|
||||
|
||||
/// Which top-level screen is on display. Exactly one at a time — replacing
|
||||
/// the `show-launch` / `show-library` / `show-identity` booleans, with
|
||||
/// develop as "none of the above" wired into every conditional that drew any
|
||||
/// of the other three. Those conditionals compared four and five booleans at
|
||||
/// once to rule out two screens being true together; comparing one value to
|
||||
/// a variant cannot be wrong in that way.
|
||||
///
|
||||
/// `develop` is listed first, and so is the type's default: it is what the
|
||||
/// old booleans meant when every one of them was false, which is the state
|
||||
/// files named on the command line stay in permanently — there is no
|
||||
/// library behind them to switch to — and the state the window briefly
|
||||
/// holds at construction, before `lib.rs::run` chooses.
|
||||
export enum View {
|
||||
develop,
|
||||
library,
|
||||
identity,
|
||||
launch,
|
||||
}
|
||||
|
||||
/// Which page, if any, is drawn over the current `View`. `settings`,
|
||||
/// `import` and `merge` are reachable from more than one `View` — Settings
|
||||
/// from the library and from develop, Import and Merge from the library —
|
||||
/// and are drawn outermost so the view underneath is torn down rather than
|
||||
/// nested inside the one it is about to change. `none` is the ordinary case,
|
||||
/// and the type's default.
|
||||
///
|
||||
/// Kept apart from `View` rather than folded into it as three more variants:
|
||||
/// closing a page has to return to whichever view was already current, and
|
||||
/// today that works because the view's own property is left untouched while
|
||||
/// a page sits over it. Three more `View` variants would need a second field
|
||||
/// remembering what to return to; a separate, single-valued `Page` needs
|
||||
/// nothing to remember.
|
||||
export enum Page {
|
||||
none,
|
||||
settings,
|
||||
import,
|
||||
merge,
|
||||
}
|
||||
|
||||
export component AppWindow inherits Window {
|
||||
title: "DarkRoom";
|
||||
// The one raster asset in the UI, and the exception that the header of
|
||||
@@ -184,11 +223,16 @@ export component AppWindow inherits Window {
|
||||
/// remembered across photographs, which is state no screen holds.
|
||||
callback inspect-toggled(float, float);
|
||||
|
||||
// --- active view (FR-UI-8) ---
|
||||
//
|
||||
// The four top-level screens share one property; see `View`. Rust is the
|
||||
// only writer — nothing in this file assigns to it — so `in` is enough.
|
||||
in property <View> active-view: View.develop;
|
||||
|
||||
// --- launch screen (FR-NC-1, FR-NC-4) ---
|
||||
//
|
||||
// The app opens here when no library is configured, and returns here to
|
||||
// sign out or switch account.
|
||||
in property <bool> show-launch: false;
|
||||
in property <bool> launch-signed-in: false;
|
||||
in property <string> launch-account: "";
|
||||
in property <string> launch-root: "";
|
||||
@@ -228,13 +272,12 @@ export component AppWindow inherits Window {
|
||||
//
|
||||
// Shown after a library is opened, before an image is chosen. Cells are a
|
||||
// window over the catalog, not the whole of it.
|
||||
in property <bool> show-library: false;
|
||||
/// Whether the grid is actually on screen — the condition the `if` below
|
||||
/// is written with, hoisted so Rust can read the same answer.
|
||||
///
|
||||
/// **`show-library` is not that answer.** It says "the library rather than
|
||||
/// develop", and stays true while Settings, Import, People or the launch
|
||||
/// screen replaces the window. The grid subtree is torn down in all four
|
||||
/// **`active-view == View.library` is not enough on its own.** The view
|
||||
/// stays `library` while Settings, Import, Merge or People replaces the
|
||||
/// window as a page over it. The grid subtree is torn down in all four
|
||||
/// cases, and a Flickable being destroyed passes its viewport through zero
|
||||
/// on the way out — which reaches `on_library_scrolled` as a scroll to the
|
||||
/// top of the library and overwrote the position the user was at. That is
|
||||
@@ -243,8 +286,7 @@ export component AppWindow inherits Window {
|
||||
/// So the guard has to be this, and the `if` has to be spelled from it, or
|
||||
/// the two can drift apart again.
|
||||
out property <bool> library-visible:
|
||||
!root.show-import && !root.show-merge && !root.show-settings && !root.show-identity
|
||||
&& !root.show-launch && root.show-library;
|
||||
root.active-page == Page.none && root.active-view == View.library;
|
||||
in-out property <[LibraryCell]> library-cells;
|
||||
in property <int> library-total: 0;
|
||||
// --- background activity (FR-CAT-1, FR-NC-6c) ---
|
||||
@@ -396,8 +438,7 @@ export component AppWindow inherits Window {
|
||||
// A third top-level screen rather than a panel: naming a cluster and
|
||||
// pulling a stranger out of it are tasks with their own rhythm, and they
|
||||
// need the whole window. Gated the same way the other screens are, so
|
||||
// exactly one is ever up.
|
||||
in property <bool> show-identity: false;
|
||||
// exactly one is ever up — see `View`.
|
||||
in property <[IdentityPerson]> identity-people;
|
||||
in property <[IdentityFace]> identity-faces;
|
||||
in property <int> identity-selected: -1;
|
||||
@@ -780,14 +821,14 @@ export component AppWindow inherits Window {
|
||||
|
||||
// --- settings (FR-EXP-1, FR-EXP-3, FR-NC-6a) ---
|
||||
//
|
||||
// A page rather than an overlay, and the outermost of the view conditions
|
||||
// below: it is reachable from the library and from develop, so guarding it
|
||||
// with `!show-library` or `!show-launch` would make which one you came from
|
||||
// decide whether it appears.
|
||||
// A page rather than an overlay, and outermost among the pages drawn over
|
||||
// a view: it is reachable from the library and from develop, so guarding
|
||||
// it with which view was current would make which one you came from
|
||||
// decide whether it appears. See `Page`.
|
||||
//
|
||||
// Every control saves on change (see `settings_ui.rs`), so there is no
|
||||
// dirty state here and nothing to confirm on the way out.
|
||||
in-out property <bool> show-settings: false;
|
||||
in-out property <Page> active-page: Page.none;
|
||||
|
||||
// --- import (FR-CAT-10, FR-CAT-11, FR-NC-7a) -------------------------
|
||||
//
|
||||
@@ -798,7 +839,6 @@ export component AppWindow inherits Window {
|
||||
// Unlike Settings, this page holds a *decision* rather than a set of saved
|
||||
// preferences, which is why it carries `import-can-start` and a running
|
||||
// state: everything here exists to be committed or abandoned.
|
||||
in-out property <bool> show-import: false;
|
||||
/// Whether this platform can import at all — see `dr_plat::imports_supported`.
|
||||
in property <bool> import-supported: false;
|
||||
|
||||
@@ -829,7 +869,6 @@ export component AppWindow inherits Window {
|
||||
// TRACES: FR-MRG-1 | FR-MRG-7
|
||||
// The merge page, on the import page's model: a decision to be
|
||||
// committed or abandoned, with a running state, over the library.
|
||||
in-out property <bool> show-merge: false;
|
||||
in property <string> merge-stage: "";
|
||||
in property <bool> merge-running: false;
|
||||
in property <float> merge-fraction: 0.0;
|
||||
@@ -1266,12 +1305,12 @@ in property <bool> panel-visible: true;
|
||||
}
|
||||
|
||||
// Settings, over everything. First in the file and first in z-order so the
|
||||
// conditions below can be read as "and settings is not open".
|
||||
// conditions below can be read as "and no page is open".
|
||||
// Outermost with the settings page, and before it: both are reachable
|
||||
// from the library and from develop, so guarding either with
|
||||
// `!show-library` would make which view you came from decide whether
|
||||
// from the library and from develop, so guarding either with which
|
||||
// view was current would make which view you came from decide whether
|
||||
// it appears.
|
||||
if root.show-import: ImportPage {
|
||||
if root.active-page == Page.import: ImportPage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -1313,7 +1352,7 @@ in property <bool> panel-visible: true;
|
||||
close() => { root.import-close(); }
|
||||
}
|
||||
|
||||
if !root.show-import && root.show-merge: MergePage {
|
||||
if root.active-page == Page.merge: MergePage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
stage: root.merge-stage;
|
||||
@@ -1346,7 +1385,7 @@ in property <bool> panel-visible: true;
|
||||
close() => { root.merge-close(); }
|
||||
}
|
||||
|
||||
if !root.show-import && !root.show-merge && root.show-settings: SettingsPage {
|
||||
if root.active-page == Page.settings: SettingsPage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -1482,8 +1521,8 @@ in property <bool> panel-visible: true;
|
||||
}
|
||||
|
||||
// Like the launch screen, this replaces the window rather than
|
||||
// overlaying it — see `show-identity`.
|
||||
if !root.show-import && !root.show-merge && !root.show-settings && root.show-identity: IdentityScreen {
|
||||
// overlaying it — see `View`.
|
||||
if root.active-page == Page.none && root.active-view == View.identity: IdentityScreen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
people: root.identity-people;
|
||||
@@ -1541,7 +1580,7 @@ in property <bool> panel-visible: true;
|
||||
|
||||
// The launch screen replaces the whole window rather than overlaying it:
|
||||
// there is no library to look at until an account is configured.
|
||||
if !root.show-import && !root.show-merge && !root.show-settings && !root.show-identity && root.show-launch: LaunchScreen {
|
||||
if root.active-page == Page.none && root.active-view == View.launch: LaunchScreen {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
signed-in: root.launch-signed-in;
|
||||
@@ -1835,7 +1874,7 @@ in property <bool> panel-visible: true;
|
||||
}
|
||||
}
|
||||
|
||||
if !root.show-import && !root.show-merge && !root.show-settings && !root.show-identity && !root.show-launch && !root.show-library: VerticalLayout {
|
||||
if root.active-page == Page.none && root.active-view == View.develop: VerticalLayout {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user