Compare commits
9 commits
0df32b8143
...
0ac76478a5
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ac76478a5 | |||
| 2c68b94084 | |||
|
|
5185d93c03 | ||
| 8a24b4711d | |||
| 4ef6f8aace | |||
| bae77a7fbf | |||
| b87c07ae58 | |||
| 125b00f8ed | |||
| 52ead3dcfa |
5 changed files with 123 additions and 51 deletions
|
|
@ -1,37 +0,0 @@
|
||||||
cancel = Têk bibe
|
|
||||||
accessibility = Gihîştin
|
|
||||||
.screen-reader = Xwînera dîmenderê
|
|
||||||
.magnifier = Mezinker
|
|
||||||
.high-contrast = Dijberiya bilind
|
|
||||||
.invert-colors = Rengên berevajîkirî
|
|
||||||
authenticating = Tê rastandin...
|
|
||||||
type-username = Navê bikarhêner:
|
|
||||||
restart = Ji nû ve bide destpêkirin
|
|
||||||
user = Bikarhêner
|
|
||||||
caps-lock = Caps Lock çalak e.
|
|
||||||
enter-user = Navê bi destan têxîne...
|
|
||||||
keyboard-layout = Awayê kilîtdankê
|
|
||||||
restart-now = Niha ji nû ve bide destpêkirin?
|
|
||||||
restart-timeout =
|
|
||||||
Pergal wê xweber were jinûvedestpêkirin
|
|
||||||
{ $seconds ->
|
|
||||||
[0] niha
|
|
||||||
[1] di 1 çirke de
|
|
||||||
*[other] di { $seconds } çirke de.
|
|
||||||
}
|
|
||||||
session = Danaşîn
|
|
||||||
shutdown = Vemrîne
|
|
||||||
shutdown-now = Niha vemrîne?
|
|
||||||
shutdown-timeout =
|
|
||||||
Pergal wê xweber were vemirandin
|
|
||||||
{ $seconds ->
|
|
||||||
[0] niha.
|
|
||||||
[1] di 1 çirke de.
|
|
||||||
*[other] di { $seconds } çirke de.
|
|
||||||
}
|
|
||||||
suspend = Rawestîne
|
|
||||||
auth-error-default = Rastandinê têk çû. Tika ye dîsa hewl bide.
|
|
||||||
auth-error-credentials = Borînpeyv şaş e. Tika ye awayê kilîtdankê xwe kontrol bike û dîsa hewl bide.
|
|
||||||
auth-error-denied = Gihîştin hate astengkirin.
|
|
||||||
auth-error-maxtries = Gelek hewldanên rastandinê yên şaş.
|
|
||||||
auth-error-account = Jimarê bikarhêner tune ye yan jî neçalak e.
|
|
||||||
|
|
@ -27,7 +27,7 @@ accessibility = Специальные возможности
|
||||||
.high-contrast = Высокая контрастность
|
.high-contrast = Высокая контрастность
|
||||||
.invert-colors = Инверсия цветов
|
.invert-colors = Инверсия цветов
|
||||||
caps-lock = Включён Caps Lock.
|
caps-lock = Включён Caps Lock.
|
||||||
enter-user = Ввести имя вручную...
|
enter-user = Введите имя вручную...
|
||||||
type-username = Имя пользователя:
|
type-username = Имя пользователя:
|
||||||
authenticating = Аутентификация…
|
authenticating = Аутентификация…
|
||||||
auth-error-default = Сбой аутентификации. Повторите попытку.
|
auth-error-default = Сбой аутентификации. Повторите попытку.
|
||||||
|
|
|
||||||
14
justfile
14
justfile
|
|
@ -92,15 +92,15 @@ vendor:
|
||||||
echo 'directory = "vendor"' >> .cargo/config.toml
|
echo 'directory = "vendor"' >> .cargo/config.toml
|
||||||
echo >> .cargo/config.toml
|
echo >> .cargo/config.toml
|
||||||
echo '[env]' >> .cargo/config.toml
|
echo '[env]' >> .cargo/config.toml
|
||||||
if [ -z "${SOURCE_DATE_EPOCH}" ]; then
|
if [ -n "${SOURCE_DATE_EPOCH}" ]
|
||||||
SOURCE_DATE_EPOCH=$(git log -1 --format='%ct')
|
then
|
||||||
|
source_date="$(date -d "@${SOURCE_DATE_EPOCH}" "+%Y-%m-%d")"
|
||||||
|
echo "VERGEN_GIT_COMMIT_DATE = \"${source_date}\"" >> .cargo/config.toml
|
||||||
fi
|
fi
|
||||||
if [ -z "${SOURCE_GIT_HASH}" ]; then
|
if [ -n "${SOURCE_GIT_HASH}" ]
|
||||||
SOURCE_GIT_HASH=$(git rev-parse HEAD)
|
then
|
||||||
|
echo "VERGEN_GIT_SHA = \"${SOURCE_GIT_HASH}\"" >> .cargo/config.toml
|
||||||
fi
|
fi
|
||||||
source_date="$(date -d "@${SOURCE_DATE_EPOCH}" "+%Y-%m-%d")"
|
|
||||||
echo "VERGEN_GIT_COMMIT_DATE = \"${source_date}\"" >> .cargo/config.toml
|
|
||||||
echo "VERGEN_GIT_SHA = \"${SOURCE_GIT_HASH}\"" >> .cargo/config.toml
|
|
||||||
tar pcf vendor.tar .cargo vendor
|
tar pcf vendor.tar .cargo vendor
|
||||||
rm -rf .cargo vendor
|
rm -rf .cargo vendor
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -390,6 +390,7 @@ pub enum Message {
|
||||||
HighContrast(bool),
|
HighContrast(bool),
|
||||||
InvertColors(bool),
|
InvertColors(bool),
|
||||||
WaylandUpdate(WaylandUpdate),
|
WaylandUpdate(WaylandUpdate),
|
||||||
|
SpinnerTick,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<common::Message> for Message {
|
impl From<common::Message> for Message {
|
||||||
|
|
@ -419,6 +420,8 @@ pub struct App {
|
||||||
|
|
||||||
accessibility: Accessibility,
|
accessibility: Accessibility,
|
||||||
authenticating: bool,
|
authenticating: bool,
|
||||||
|
spinner_rotation: f32,
|
||||||
|
spinner_handle: Option<cosmic::iced::task::Handle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -899,7 +902,14 @@ impl App {
|
||||||
widget::row::with_capacity(2)
|
widget::row::with_capacity(2)
|
||||||
.spacing(8.0)
|
.spacing(8.0)
|
||||||
.align_y(Alignment::Center)
|
.align_y(Alignment::Center)
|
||||||
.push(widget::indeterminate_circular().size(16.0).bar_height(2.0))
|
.push(
|
||||||
|
widget::icon::from_name("process-working-symbolic")
|
||||||
|
.size(16)
|
||||||
|
.icon()
|
||||||
|
.rotation(iced::Rotation::Floating(iced::Radians(
|
||||||
|
self.spinner_rotation.to_radians(),
|
||||||
|
))),
|
||||||
|
)
|
||||||
.push(widget::text(fl!("authenticating"))),
|
.push(widget::text(fl!("authenticating"))),
|
||||||
)
|
)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
|
|
@ -1163,6 +1173,8 @@ impl cosmic::Application for App {
|
||||||
randr_list: None,
|
randr_list: None,
|
||||||
surface_id_pairs: Vec::new(),
|
surface_id_pairs: Vec::new(),
|
||||||
authenticating: false,
|
authenticating: false,
|
||||||
|
spinner_rotation: 0.0,
|
||||||
|
spinner_handle: None,
|
||||||
};
|
};
|
||||||
(app, Task::batch(tasks))
|
(app, Task::batch(tasks))
|
||||||
}
|
}
|
||||||
|
|
@ -1470,12 +1482,39 @@ impl cosmic::Application for App {
|
||||||
self.common.error_opt = None;
|
self.common.error_opt = None;
|
||||||
self.authenticating = true;
|
self.authenticating = true;
|
||||||
self.send_request(Request::PostAuthMessageResponse { response });
|
self.send_request(Request::PostAuthMessageResponse { response });
|
||||||
|
|
||||||
|
// Start spinner animation if not already running
|
||||||
|
if self.spinner_handle.is_none() {
|
||||||
|
let (spinner_task, handle) =
|
||||||
|
cosmic::task::stream(cosmic::iced::stream::channel(
|
||||||
|
1,
|
||||||
|
|mut msg_tx: iced::futures::channel::mpsc::Sender<_>| async move {
|
||||||
|
let mut interval = time::interval(Duration::from_millis(16)); // ~60fps
|
||||||
|
loop {
|
||||||
|
msg_tx
|
||||||
|
.send(cosmic::Action::App(Message::SpinnerTick))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
interval.tick().await;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.abortable();
|
||||||
|
self.spinner_handle = Some(handle);
|
||||||
|
return spinner_task;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message::Login => {
|
Message::Login => {
|
||||||
self.common.prompt_opt = None;
|
self.common.prompt_opt = None;
|
||||||
self.common.error_opt = None;
|
self.common.error_opt = None;
|
||||||
self.authenticating = false;
|
self.authenticating = false;
|
||||||
|
|
||||||
|
// Stop spinner animation
|
||||||
|
if let Some(handle) = self.spinner_handle.take() {
|
||||||
|
handle.abort();
|
||||||
|
}
|
||||||
|
self.spinner_rotation = 0.0;
|
||||||
|
|
||||||
match self.flags.sessions.get(&self.selected_session).cloned() {
|
match self.flags.sessions.get(&self.selected_session).cloned() {
|
||||||
Some((cmd, env)) => {
|
Some((cmd, env)) => {
|
||||||
self.send_request(Request::StartSession { cmd, env });
|
self.send_request(Request::StartSession { cmd, env });
|
||||||
|
|
@ -1488,6 +1527,12 @@ impl cosmic::Application for App {
|
||||||
self.common.error_opt = Some(error);
|
self.common.error_opt = Some(error);
|
||||||
self.authenticating = false;
|
self.authenticating = false;
|
||||||
|
|
||||||
|
// Stop spinner animation
|
||||||
|
if let Some(handle) = self.spinner_handle.take() {
|
||||||
|
handle.abort();
|
||||||
|
}
|
||||||
|
self.spinner_rotation = 0.0;
|
||||||
|
|
||||||
self.send_request(Request::CancelSession);
|
self.send_request(Request::CancelSession);
|
||||||
}
|
}
|
||||||
Message::Reconnect => {
|
Message::Reconnect => {
|
||||||
|
|
@ -1818,6 +1863,10 @@ impl cosmic::Application for App {
|
||||||
};
|
};
|
||||||
return reposition_subsurface(*subsurface_id, loc.x as i32, loc.y as i32);
|
return reposition_subsurface(*subsurface_id, loc.x as i32, loc.y as i32);
|
||||||
}
|
}
|
||||||
|
Message::SpinnerTick => {
|
||||||
|
// Update spinner rotation angle (360 degrees per second = 6 degrees per frame at 60fps)
|
||||||
|
self.spinner_rotation = (self.spinner_rotation + 6.0) % 360.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,7 @@ pub enum Message {
|
||||||
Error(String),
|
Error(String),
|
||||||
Lock,
|
Lock,
|
||||||
Unlock,
|
Unlock,
|
||||||
|
SpinnerTick,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<common::Message> for Message {
|
impl From<common::Message> for Message {
|
||||||
|
|
@ -311,6 +312,8 @@ pub struct App {
|
||||||
inhibit_opt: Option<Arc<OwnedFd>>,
|
inhibit_opt: Option<Arc<OwnedFd>>,
|
||||||
value_tx_opt: Option<mpsc::Sender<String>>,
|
value_tx_opt: Option<mpsc::Sender<String>>,
|
||||||
authenticating: bool,
|
authenticating: bool,
|
||||||
|
spinner_rotation: f32,
|
||||||
|
spinner_handle: Option<cosmic::iced::task::Handle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -563,7 +566,14 @@ impl App {
|
||||||
widget::row::with_capacity(2)
|
widget::row::with_capacity(2)
|
||||||
.spacing(8.0)
|
.spacing(8.0)
|
||||||
.align_y(Alignment::Center)
|
.align_y(Alignment::Center)
|
||||||
.push(widget::indeterminate_circular().size(16.0).bar_height(2.0))
|
.push(
|
||||||
|
widget::icon::from_name("process-working-symbolic")
|
||||||
|
.size(16)
|
||||||
|
.icon()
|
||||||
|
.rotation(iced::Rotation::Floating(iced::Radians(
|
||||||
|
self.spinner_rotation.to_radians(),
|
||||||
|
))),
|
||||||
|
)
|
||||||
.push(widget::text(fl!("authenticating"))),
|
.push(widget::text(fl!("authenticating"))),
|
||||||
)
|
)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
|
|
@ -665,6 +675,8 @@ impl cosmic::Application for App {
|
||||||
inhibit_opt: None,
|
inhibit_opt: None,
|
||||||
value_tx_opt: None,
|
value_tx_opt: None,
|
||||||
authenticating: false,
|
authenticating: false,
|
||||||
|
spinner_rotation: 0.0,
|
||||||
|
spinner_handle: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let task = if cfg!(feature = "logind") {
|
let task = if cfg!(feature = "logind") {
|
||||||
|
|
@ -1035,10 +1047,39 @@ impl cosmic::Application for App {
|
||||||
self.authenticating = true;
|
self.authenticating = true;
|
||||||
match self.value_tx_opt.take() {
|
match self.value_tx_opt.take() {
|
||||||
Some(value_tx) => {
|
Some(value_tx) => {
|
||||||
return cosmic::task::future(async move {
|
// Start spinner animation if not already running
|
||||||
value_tx.send(value).await.unwrap();
|
if self.spinner_handle.is_none() {
|
||||||
Message::Channel(value_tx)
|
let (spinner_task, handle) =
|
||||||
});
|
cosmic::task::stream(cosmic::iced::stream::channel(
|
||||||
|
1,
|
||||||
|
|mut msg_tx: futures::channel::mpsc::Sender<_>| async move {
|
||||||
|
let mut interval =
|
||||||
|
tokio::time::interval(Duration::from_millis(16)); // ~60fps
|
||||||
|
loop {
|
||||||
|
msg_tx
|
||||||
|
.send(cosmic::Action::App(Message::SpinnerTick))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
interval.tick().await;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.abortable();
|
||||||
|
self.spinner_handle = Some(handle);
|
||||||
|
|
||||||
|
return Task::batch([
|
||||||
|
spinner_task,
|
||||||
|
cosmic::task::future(async move {
|
||||||
|
value_tx.send(value).await.unwrap();
|
||||||
|
Message::Channel(value_tx)
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return cosmic::task::future(async move {
|
||||||
|
value_tx.send(value).await.unwrap();
|
||||||
|
Message::Channel(value_tx)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => tracing::warn!("tried to submit when value_tx_opt not set"),
|
None => tracing::warn!("tried to submit when value_tx_opt not set"),
|
||||||
}
|
}
|
||||||
|
|
@ -1057,6 +1098,16 @@ impl cosmic::Application for App {
|
||||||
Message::Error(error) => {
|
Message::Error(error) => {
|
||||||
self.common.error_opt = Some(error);
|
self.common.error_opt = Some(error);
|
||||||
self.authenticating = false;
|
self.authenticating = false;
|
||||||
|
|
||||||
|
// Stop spinner animation
|
||||||
|
if let Some(handle) = self.spinner_handle.take() {
|
||||||
|
handle.abort();
|
||||||
|
}
|
||||||
|
self.spinner_rotation = 0.0;
|
||||||
|
}
|
||||||
|
Message::SpinnerTick => {
|
||||||
|
// Update spinner rotation angle (360 degrees per second = 6 degrees per frame at 60fps)
|
||||||
|
self.spinner_rotation = (self.spinner_rotation + 6.0) % 360.0;
|
||||||
}
|
}
|
||||||
Message::Lock => match self.state {
|
Message::Lock => match self.state {
|
||||||
State::Unlocked => {
|
State::Unlocked => {
|
||||||
|
|
@ -1068,6 +1119,10 @@ impl cosmic::Application for App {
|
||||||
self.value_tx_opt = None;
|
self.value_tx_opt = None;
|
||||||
// Reset authenticating state
|
// Reset authenticating state
|
||||||
self.authenticating = false;
|
self.authenticating = false;
|
||||||
|
if let Some(handle) = self.spinner_handle.take() {
|
||||||
|
handle.abort();
|
||||||
|
}
|
||||||
|
self.spinner_rotation = 0.0;
|
||||||
// Try to create lockfile when locking
|
// Try to create lockfile when locking
|
||||||
if let Some(ref lockfile) = self.flags.lockfile_opt
|
if let Some(ref lockfile) = self.flags.lockfile_opt
|
||||||
&& let Err(err) = fs::File::create(lockfile)
|
&& let Err(err) = fs::File::create(lockfile)
|
||||||
|
|
@ -1096,6 +1151,11 @@ impl cosmic::Application for App {
|
||||||
// Stop authenticating
|
// Stop authenticating
|
||||||
self.authenticating = false;
|
self.authenticating = false;
|
||||||
|
|
||||||
|
// Stop spinner animation
|
||||||
|
if let Some(handle) = self.spinner_handle.take() {
|
||||||
|
handle.abort();
|
||||||
|
}
|
||||||
|
self.spinner_rotation = 0.0;
|
||||||
// Try to delete lockfile when unlocking
|
// Try to delete lockfile when unlocking
|
||||||
if let Some(ref lockfile) = self.flags.lockfile_opt
|
if let Some(ref lockfile) = self.flags.lockfile_opt
|
||||||
&& let Err(err) = fs::remove_file(lockfile)
|
&& let Err(err) = fs::remove_file(lockfile)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue