Initial Commit, Basic Navigation implemented
This commit is contained in:
parent
60c3a2da87
commit
d531356693
16 changed files with 6874 additions and 0 deletions
30
ui/appwindow.slint
Normal file
30
ui/appwindow.slint
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { Button, VerticalBox, HorizontalBox } from "std-widgets.slint";
|
||||
import { SideBar } from "sidebar.slint";
|
||||
import { AboutPage } from "pages/about_page.slint";
|
||||
import { SettingsPage, SettingsPageInterface, JNCSettingsInterface } from "pages/settings_page.slint";
|
||||
import { UploadPage, UploadPageInterface } from "pages/upload_page.slint";
|
||||
|
||||
export { SettingsPageInterface, JNCSettingsInterface, UploadPageInterface }
|
||||
|
||||
export component AppWindow inherits Window {
|
||||
title: "Kavita Upload Tool";
|
||||
preferred-width: 1024px;
|
||||
preferred-height: 720px;
|
||||
HorizontalLayout {
|
||||
VerticalBox {
|
||||
padding-right: 0px;
|
||||
side-bar := SideBar {
|
||||
title: "Kavita Upload Tool";
|
||||
model: [
|
||||
"Upload Tool",
|
||||
"Settings",
|
||||
"About"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (side-bar.current-item == 0) : UploadPage {}
|
||||
if (side-bar.current-item == 1) : SettingsPage {}
|
||||
if (side-bar.current-item == 2) : AboutPage {}
|
||||
}
|
||||
}
|
13
ui/pages/about_page.slint
Normal file
13
ui/pages/about_page.slint
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { VerticalBox, Palette } from "std-widgets.slint";
|
||||
|
||||
export component AboutPage inherits VerticalBox {
|
||||
Rectangle {
|
||||
border-width: 1px;
|
||||
border-radius: 4px;
|
||||
border-color: Palette.border;
|
||||
background: Palette.alternate-background;
|
||||
Text {
|
||||
text: "ToDo: Add Author Info and Link to Repository";
|
||||
}
|
||||
}
|
||||
}
|
131
ui/pages/settings_page.slint
Normal file
131
ui/pages/settings_page.slint
Normal file
|
@ -0,0 +1,131 @@
|
|||
import { VerticalBox, Palette, TextEdit, HorizontalBox, ScrollView, LineEdit, Button } from "std-widgets.slint";
|
||||
|
||||
export enum LoginState {
|
||||
LoggedIn,
|
||||
LoggedOut,
|
||||
Processing,
|
||||
LoginError,
|
||||
LoginTimeout
|
||||
}
|
||||
|
||||
export global JNCSettingsInterface {
|
||||
in-out property <LoginState> login_state: LoginState.LoggedOut;
|
||||
in-out property <string> login_timeout;
|
||||
in-out property <string> otp_code;
|
||||
in-out property <int> series_count: 0;
|
||||
in-out property <int> book_count: 0;
|
||||
|
||||
callback start_login();
|
||||
callback logout();
|
||||
callback refresh_library();
|
||||
}
|
||||
|
||||
export global SettingsPageInterface {
|
||||
|
||||
}
|
||||
|
||||
component SettingsMember inherits Rectangle {
|
||||
border-width: 1px;
|
||||
border-radius: 4px;
|
||||
border-color: Palette.border;
|
||||
background: Palette.alternate-background;
|
||||
VerticalBox {
|
||||
alignment: start;
|
||||
spacing: 4px;
|
||||
@children
|
||||
}
|
||||
}
|
||||
|
||||
component StringSetting inherits HorizontalBox {
|
||||
in property <string> name;
|
||||
in property <string> placeholder: "" ;
|
||||
in property <length> w: 100px;
|
||||
in-out property <string> value;
|
||||
|
||||
alignment: start;
|
||||
height: 24px;
|
||||
Text {
|
||||
font-size: 12px;
|
||||
height: self.font-size + 8px;
|
||||
vertical-alignment: center;
|
||||
text: name;
|
||||
}
|
||||
LineEdit {
|
||||
font-size: 12px;
|
||||
preferred-width: w + 4px;
|
||||
height: self.font-size + 8px;
|
||||
placeholder-text: placeholder;
|
||||
text <=> value;
|
||||
}
|
||||
}
|
||||
|
||||
export component SettingsPage inherits VerticalBox {
|
||||
SettingsMember {
|
||||
Text {
|
||||
text: "Kavita Settings (sftp)";
|
||||
}
|
||||
|
||||
StringSetting {
|
||||
name: "Server:";
|
||||
placeholder: "XXX.XXX.XXX.XXX";
|
||||
value: "";
|
||||
w: 120px;
|
||||
}
|
||||
StringSetting {
|
||||
name: "Username:";
|
||||
placeholder: "User";
|
||||
value: "";
|
||||
w: 80px;
|
||||
}
|
||||
}
|
||||
SettingsMember {
|
||||
Text {
|
||||
text: "J-Novel Club Settings";
|
||||
}
|
||||
|
||||
if JNCSettingsInterface.login_state == LoginState.LoggedOut : HorizontalLayout {
|
||||
alignment: start;
|
||||
Button {
|
||||
text: "Log In";
|
||||
clicked => {JNCSettingsInterface.start_login()}
|
||||
}
|
||||
}
|
||||
if JNCSettingsInterface.login_state == LoginState.Processing : HorizontalBox {
|
||||
otp := Text {
|
||||
text: JNCSettingsInterface.otp_code;
|
||||
}
|
||||
Button {
|
||||
text: "Copy";
|
||||
clicked => {}
|
||||
}
|
||||
Text {
|
||||
text: "Awaiting Login Confirmation. \{JNCSettingsInterface.login_timeout} until expiry.";
|
||||
}
|
||||
}
|
||||
if JNCSettingsInterface.login_state == LoginState.LoggedIn : VerticalBox {
|
||||
HorizontalBox {
|
||||
Text {
|
||||
text: "Logged In.";
|
||||
}
|
||||
Button {
|
||||
text: "Log Out";
|
||||
clicked => {JNCSettingsInterface.logout()}
|
||||
}
|
||||
}
|
||||
HorizontalBox {
|
||||
Text {
|
||||
text: "Library: \{JNCSettingsInterface.series_count} Series, \{JNCSettingsInterface.book_count} Books loaded";
|
||||
}
|
||||
Button {
|
||||
text: "refresh";
|
||||
clicked => {JNCSettingsInterface.refresh_library()}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SettingsMember {
|
||||
Text {
|
||||
text: "Manual Parser Settings";
|
||||
}
|
||||
}
|
||||
}
|
58
ui/pages/upload_page.slint
Normal file
58
ui/pages/upload_page.slint
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { VerticalBox, Palette, TabWidget, HorizontalBox, Button } from "std-widgets.slint";
|
||||
|
||||
export global UploadPageInterface {
|
||||
in-out property <bool> prev_button_enabled: false;
|
||||
in-out property <bool> next_button_enabled: true;
|
||||
|
||||
pure callback paginate_tabs(int) -> int;
|
||||
}
|
||||
|
||||
export component UploadPage inherits VerticalBox {
|
||||
Rectangle {
|
||||
border-width: 1px;
|
||||
border-radius: 4px;
|
||||
border-color: Palette.border;
|
||||
background: Palette.alternate-background;
|
||||
VerticalLayout {
|
||||
property <int> current_tab: UploadPageInterface.paginate_tabs(tabs.current-index);
|
||||
tabs := TabWidget {
|
||||
Tab {
|
||||
title: "Parser";
|
||||
Text {
|
||||
text: "Parser Settings here";
|
||||
}
|
||||
}
|
||||
Tab {
|
||||
title: "Metadata";
|
||||
Text {
|
||||
text: "Metadata manipulation here";
|
||||
}
|
||||
}
|
||||
Tab {
|
||||
title: "Upload";
|
||||
Text {
|
||||
text: "Upload Stuff here";
|
||||
}
|
||||
}
|
||||
}
|
||||
HorizontalBox {
|
||||
previous := Button {
|
||||
text: "Previous";
|
||||
enabled: UploadPageInterface.prev_button_enabled;
|
||||
clicked => {tabs.current-index -= 1}
|
||||
}
|
||||
Text {
|
||||
text: "\{current_tab + 1}/3";
|
||||
vertical-alignment: center;
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
next := Button {
|
||||
text: "Next";
|
||||
enabled: UploadPageInterface.next_button_enabled;
|
||||
clicked => {tabs.current-index += 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
129
ui/sidebar.slint
Normal file
129
ui/sidebar.slint
Normal file
|
@ -0,0 +1,129 @@
|
|||
import { HorizontalBox, VerticalBox, Palette } from "std-widgets.slint";
|
||||
|
||||
component SideBarItem inherits Rectangle {
|
||||
in property <bool> selected;
|
||||
in property <bool> has-focus;
|
||||
in-out property <string> text <=> label.text;
|
||||
|
||||
callback clicked <=> touch.clicked;
|
||||
|
||||
min-height: l.preferred-height;
|
||||
|
||||
states [
|
||||
pressed when touch.pressed : {
|
||||
state.opacity: 0.8;
|
||||
}
|
||||
hover when touch.has-hover : {
|
||||
state.opacity: 0.6;
|
||||
}
|
||||
selected when root.selected : {
|
||||
state.opacity: 1;
|
||||
}
|
||||
focused when root.has-focus : {
|
||||
state.opacity: 0.8;
|
||||
}
|
||||
]
|
||||
|
||||
state := Rectangle {
|
||||
opacity: 0;
|
||||
background: Palette.background;
|
||||
|
||||
animate opacity { duration: 150ms; }
|
||||
}
|
||||
|
||||
l := HorizontalBox {
|
||||
y: (parent.height - self.height) / 2;
|
||||
spacing: 0px;
|
||||
|
||||
label := Text {
|
||||
vertical-alignment: center;
|
||||
}
|
||||
}
|
||||
|
||||
touch := TouchArea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
export component SideBar inherits Rectangle {
|
||||
in property <[string]> model: [];
|
||||
in property <string> title <=> label.text;
|
||||
out property <int> current-item: 0;
|
||||
out property <int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
|
||||
|
||||
width: 180px;
|
||||
forward-focus: fs;
|
||||
accessible-role: tab;
|
||||
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
|
||||
|
||||
Rectangle {
|
||||
background: Palette.alternate-background;
|
||||
border-width: 1px;
|
||||
border-radius: 4px;
|
||||
border-color: Palette.border;
|
||||
|
||||
fs := FocusScope {
|
||||
key-pressed(event) => {
|
||||
if (event.text == "\n") {
|
||||
root.current-item = root.current-focused;
|
||||
return accept;
|
||||
}
|
||||
if (event.text == Key.UpArrow) {
|
||||
self.focused-tab = Math.max(self.focused-tab - 1, 0);
|
||||
return accept;
|
||||
}
|
||||
if (event.text == Key.DownArrow) {
|
||||
self.focused-tab = Math.min(self.focused-tab + 1, root.model.length - 1);
|
||||
return accept;
|
||||
}
|
||||
return reject;
|
||||
}
|
||||
|
||||
key-released(event) => {
|
||||
if (event.text == " ") {
|
||||
root.current-item = root.current-focused;
|
||||
return accept;
|
||||
}
|
||||
return reject;
|
||||
}
|
||||
|
||||
property <int> focused-tab: 0;
|
||||
|
||||
x: 0;
|
||||
width: 0; // Do not react on clicks
|
||||
}
|
||||
}
|
||||
|
||||
VerticalBox {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
alignment: start;
|
||||
|
||||
label := Text {
|
||||
font-size: 16px;
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
|
||||
navigation := VerticalLayout {
|
||||
alignment: start;
|
||||
vertical-stretch: 0;
|
||||
for item[index] in root.model : SideBarItem {
|
||||
clicked => { root.current-item = index; }
|
||||
|
||||
has-focus: index == root.current-focused;
|
||||
text: item;
|
||||
selected: index == root.current-item;
|
||||
}
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
bottom := VerticalBox {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
|
||||
@children
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue