Skip to content

Commit ada9d9e

Browse files
committed
Merge branch 'main' into collaborator
2 parents 0d921f4 + 5e234c7 commit ada9d9e

9 files changed

Lines changed: 164 additions & 37 deletions

File tree

phira/locales/zh-TW/common.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ main-character-intro =
2424
自斷壁殘垣中傳來的歌聲,被繁複樂章所縈繞的,韻律的形狀。彷彿奇蹟本身,無法用一切已知定律刻劃的謎之少女。
2525
來自未來,卻讓人覺得似乎是某種與世間本質關聯、恆久的存在。無妨,一切無形和有形的附著已隨少女的記憶模糊淡去,不見所蹤。
2626
翩翩然如禽羽的她,在聲樂交織的夢中,看見的又是什麼呢?
27-
favorites = 我的最愛
27+
favorites = 收藏庫
2828
default-fav-folder = 我的最愛
29-
favorites-online-only = 雲端資料夾只能收藏線上譜面。本地譜面:{ $charts }
29+
favorites-online-only = 雲端收藏夾只能收藏線上譜面。本地譜面:{ $charts }

phira/locales/zh-TW/favorites.ftl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
set-as-default = 設為預設
22
default = 預設
3-
create = 新建資料夾
3+
create = 新建收藏夾
44
created = 建立成功
5-
name-empty = 資料夾名稱不能為空
5+
name-empty = 收藏夾名稱不能為空
66
import = 匯入線上合集
77
imported = 已匯入
88
already-imported = 已經匯入過了
99
invalid-import = 解析輸入的目標失敗
1010
rename = 重新命名
1111
set-description = 編輯簡介
1212
set-cover = 設定封面
13-
no-charts = 所選資料夾沒有譜面,無法設定封面
13+
no-charts = 所選收藏夾沒有譜面,無法設定封面
1414
select-cover = 請選擇一個譜面作為封面
15-
delete = 刪除資料夾
16-
deleted = 資料夾已刪除
17-
delete-confirm = 確定要刪除這個資料夾嗎?(不會刪除其中的譜面)
15+
delete = 刪除收藏夾
16+
deleted = 收藏夾已刪除
17+
delete-confirm = 確定要刪除這個收藏夾嗎?(不會刪除其中的譜面)
1818
show-all = 顯示全部譜面
1919
batch-import = 匯入多個譜面
2020
updated = 已更新
@@ -29,7 +29,7 @@ synced = 同步完成
2929
upload-to-cloud = 上傳到雲端
3030
uploaded = 已上傳
3131
delete-from-cloud = 從雲端刪除
32-
delete-from-cloud-confirm = 確定要從雲端刪除這個資料夾嗎
32+
delete-from-cloud-confirm = 確定要從雲端刪除這個收藏夾嗎
3333
make-public = 設為公開
3434
make-private = 設為私人
3535
duplicate = 再製

phira/locales/zh-TW/library.ftl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@ order-by = 排序方式:{ $order }
1313
order-asc = 升序
1414
order-desc = 降序
1515
order-updated = 排序已更新
16-
order-update-failed-sort = 這能在預設排序方式下更新排序
17-
fav-synced = 我的最愛已同步
18-
fav-sync-failed = 我的最愛同步失敗
16+
order-update-failed-sort = 只能在預設排序方式下更新排序
17+
fav-synced = 收藏夾已同步
18+
fav-sync-failed = 收藏夾同步失敗
1919
multi-select-status = 已選中 { $count }
2020
multi-export = 打包多個譜面
21-
multi-create-fav = 加入到新資料夾
22-
multi-manage-fav = 管理資料夾
21+
multi-create-fav = 加入到新收藏夾
22+
multi-manage-fav = 管理收藏
2323
multi-delete = 刪除
2424
multi-delete-confirm = 確定要刪除這 { $count } 個譜面嗎?該操作無法撤銷。
2525
multi-deleted = 已刪除
2626
multi-export-title = 選擇匯出位置
2727
multi-export-no-file = 請在匯出前下載所有選中的譜面。未下載:{ $charts }
2828
multi-exporting = 匯出中 ({ $current } / { $total })
29-
exported = 已匯出
30-
multi-added-to-fav = 已加入到資料夾
31-
multi-removed-from-fav = 已從資料夾移除
29+
multi-exported = 已匯出
30+
multi-added-to-fav = 已加入到收藏夾
31+
multi-removed-from-fav = 已從收藏夾移除
3232
multi-select-all = 選取全部
3333
multi-select-invert = 反向選取
34-
fav-created = 資料夾建立成功
34+
fav-created = 收藏夾建立成功

phira/locales/zh-TW/song.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ review-edit-tags-failed = 編輯標籤失敗
9393
review-edit-tags-done = 標籤已更新
9494
mods = Mods
9595
mods-autoplay = 自動遊玩 (Auto)
96-
mods-autoplay-sub = 啟用後將無法上傳成績
96+
mods-autoplay-sub = *啟用後將無法上傳成績*
9797
mods-flip-x = X 軸翻轉 (Mirror)
9898
mods-flip-x-sub = 在 X 軸上翻轉譜面
9999
mods-fade-in = 漸顯 (Fade In)
@@ -131,7 +131,7 @@ stabilize-approved = 已通過
131131
stabilize-approved-passed = 已通過,譜面已 stable
132132
stabilize-denied = 已拒絕
133133
stabilize-denied-passed = 已拒絕,譜面已退件
134-
fav-added = 已收藏(長按以選擇其他資料夾
134+
fav-added = 已收藏(長按以選擇其他收藏夾
135135
still-loading = 仍在載入,請稍候…
136136
137137
export = 匯出

phira/src/charts_view.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
client::{Chart, ChartRef},
55
dir, get_data, get_data_mut,
66
icons::Icons,
7-
page::{ChartItem, ChartType, Fader, Illustration, CHOOSE_COVER, CHOSEN_COVER},
7+
page::{ChartItem, Fader, CHOOSE_COVER, CHOSEN_COVER},
88
popup::Popup,
99
save_data,
1010
scene::{render_release_to_refresh, SongScene, MP_PANEL},
@@ -59,12 +59,7 @@ impl ChartDisplayItem {
5959

6060
pub fn from_remote(chart: &Chart) -> Self {
6161
Self::new(
62-
Some(ChartItem {
63-
info: chart.to_info(),
64-
illu: Illustration::from_file_thumbnail(chart.illustration.clone()),
65-
local_path: None,
66-
chart_type: ChartType::Downloaded,
67-
}),
62+
Some(ChartItem::from_remote(chart)),
6863
if chart.stable_request {
6964
Some('+')
7065
} else if !chart.reviewed {

phira/src/client/model/message.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
use chrono::{DateTime, Utc};
22
use serde::Deserialize;
33

4+
#[derive(Deserialize)]
5+
pub struct MessageAction {
6+
pub name: String,
7+
pub action: String,
8+
}
9+
410
#[derive(Deserialize)]
511
#[allow(dead_code)]
612
pub struct Message {
@@ -9,4 +15,6 @@ pub struct Message {
915
pub content: String,
1016
pub author: String,
1117
pub time: DateTime<Utc>,
18+
#[serde(default)]
19+
pub actions: Vec<MessageAction>,
1220
}

phira/src/page.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use settings::SettingsPage;
2727
use tokio::sync::Notify;
2828

2929
use crate::{
30-
client::{ChartRef, File},
30+
client::{Chart, ChartRef, File},
3131
data::BriefChartInfo,
3232
dir, get_data,
3333
images::Images,
@@ -214,6 +214,15 @@ impl ChartItem {
214214
pub fn to_ref(&self) -> ChartRef {
215215
ChartRef::new_bare(self.info.id, self.local_path.as_deref())
216216
}
217+
218+
pub fn from_remote(chart: &Chart) -> Self {
219+
ChartItem {
220+
info: chart.to_info(),
221+
illu: Illustration::from_file_thumbnail(chart.illustration.clone()),
222+
local_path: None,
223+
chart_type: ChartType::Downloaded,
224+
}
225+
}
217226
}
218227

219228
#[derive(Clone, Copy)]

phira/src/page/home.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ impl Page for HomePage {
410410
return Ok(true);
411411
}
412412
if self.btn_msg.touch(touch, t) {
413-
self.next_page = Some(NextPage::Overlay(Box::new(MessagePage::new())));
413+
self.next_page = Some(NextPage::Overlay(Box::new(MessagePage::new(Arc::clone(&self.icons), s.icons.clone()))));
414414
return Ok(true);
415415
}
416416
if self.btn_settings.touch(touch, t) {

phira/src/page/message.rs

Lines changed: 123 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
prpr_l10n::tl_file!("message");
22

3-
use std::borrow::Cow;
3+
use std::{borrow::Cow, sync::Arc};
44

55
use super::{Page, SharedState};
66
use crate::{
7-
client::{recv_raw, Client, Message},
8-
get_data, get_data_mut, save_data,
7+
client::{recv_raw, Chart, Client, Message, Ptr},
8+
get_data, get_data_mut,
9+
icons::Icons,
10+
page::{ChartItem, SFader},
11+
save_data,
12+
scene::{ProfileScene, SongScene},
913
};
1014
use anyhow::Result;
1115
use chrono::Local;
1216
use macroquad::prelude::*;
1317
use prpr::{
14-
ext::{semi_black, semi_white, RectExt},
18+
ext::{open_url, semi_black, semi_white, RectExt, SafeTexture},
1519
scene::show_error,
1620
task::Task,
1721
ui::{DRectButton, Scroll, Ui},
@@ -25,10 +29,17 @@ pub struct MessagePage {
2529

2630
btns_scroll: Scroll,
2731
scroll: Scroll,
32+
33+
action_btns: Vec<DRectButton>,
34+
35+
sf: SFader,
36+
chart_task: Option<Task<Result<Arc<Chart>>>>,
37+
icons: Arc<Icons>,
38+
rank_icons: [SafeTexture; 8],
2839
}
2940

3041
impl MessagePage {
31-
pub fn new() -> Self {
42+
pub fn new(icons: Arc<Icons>, rank_icons: [SafeTexture; 8]) -> Self {
3243
Self {
3344
msgs: None,
3445
load_task: None,
@@ -37,6 +48,13 @@ impl MessagePage {
3748

3849
btns_scroll: Scroll::new(),
3950
scroll: Scroll::new(),
51+
52+
action_btns: Vec::new(),
53+
54+
sf: SFader::new(),
55+
chart_task: None,
56+
icons,
57+
rank_icons,
4058
}
4159
}
4260

@@ -53,6 +71,46 @@ impl MessagePage {
5371
Ok(recv_raw(req).await?.json().await?)
5472
}));
5573
}
74+
75+
fn execute_action(&mut self, t: f32, action: String) -> Result<()> {
76+
let (ty, param) = match action.split_once(':') {
77+
Some(it) => it,
78+
None => {
79+
warn!("invalid action: {action}");
80+
return Ok(());
81+
}
82+
};
83+
match ty {
84+
"url" => {
85+
open_url(param)?;
86+
}
87+
"chart" => {
88+
let id = match param.parse::<i32>() {
89+
Ok(it) => it,
90+
Err(_) => {
91+
warn!("invalid chart id: {param}");
92+
return Ok(());
93+
}
94+
};
95+
self.chart_task = Some(Task::new(async move { Ptr::<Chart>::new(id).fetch().await }));
96+
}
97+
"user" => {
98+
let id = match param.parse::<i32>() {
99+
Ok(it) => it,
100+
Err(_) => {
101+
warn!("invalid user id: {param}");
102+
return Ok(());
103+
}
104+
};
105+
self.sf.goto(t, ProfileScene::new(id, self.icons.user.clone(), self.rank_icons.clone()));
106+
}
107+
_ => {
108+
warn!("unknown action type: {ty}");
109+
}
110+
}
111+
112+
Ok(())
113+
}
56114
}
57115

58116
impl Page for MessagePage {
@@ -67,6 +125,9 @@ impl Page for MessagePage {
67125

68126
fn touch(&mut self, touch: &Touch, s: &mut SharedState) -> Result<bool> {
69127
let t = s.t;
128+
if self.chart_task.is_some() {
129+
return Ok(false);
130+
}
70131
if self.load_task.is_none() {
71132
if self.btns_scroll.touch(touch, t) {
72133
return Ok(true);
@@ -86,6 +147,15 @@ impl Page for MessagePage {
86147
return Ok(true);
87148
}
88149
}
150+
if let Some(index) = self.index {
151+
for (btn, action) in self.action_btns.iter_mut().zip(&msgs[index].0.actions) {
152+
if btn.touch(touch, t) {
153+
let action = action.action.clone();
154+
self.execute_action(t, action)?;
155+
return Ok(true);
156+
}
157+
}
158+
}
89159
}
90160
}
91161
if self.scroll.touch(touch, t) {
@@ -118,6 +188,29 @@ impl Page for MessagePage {
118188
self.load_task = None;
119189
}
120190
}
191+
if self.chart_task.is_some() {
192+
if let Some(res) = self.chart_task.as_mut().unwrap().take() {
193+
match res {
194+
Err(err) => {
195+
show_error(err);
196+
}
197+
Ok(chart) => {
198+
let data = get_data();
199+
let (local_path, mods) = data
200+
.charts
201+
.iter()
202+
.find(|it| it.info.id == Some(chart.id))
203+
.map(|it| (Some(it.local_path.clone()), it.mods))
204+
.unwrap_or_default();
205+
self.sf.goto(
206+
t,
207+
SongScene::new(ChartItem::from_remote(chart.as_ref()), local_path, self.icons.clone(), self.rank_icons.clone(), mods),
208+
);
209+
}
210+
}
211+
self.chart_task = None;
212+
}
213+
}
121214
Ok(())
122215
}
123216

@@ -162,10 +255,24 @@ impl Page for MessagePage {
162255
});
163256
s.render_fader(ui, |ui| {
164257
ui.fill_path(&cr.rounded(0.005), semi_black(0.4));
165-
let pad = 0.03;
166-
ui.dx(cr.x + pad + 0.01);
167-
ui.dy(cr.y + pad);
258+
168259
if let Some(msg) = self.index.and_then(|it| self.msgs.as_ref().map(|msgs| &msgs[it].0)) {
260+
let pad = 0.03;
261+
ui.scope(|ui| {
262+
ui.dx(cr.right() - pad);
263+
ui.dy(cr.bottom() - pad);
264+
self.action_btns.resize_with(msg.actions.len(), DRectButton::new);
265+
let mut r = Rect::new(0., 0., 0.28, 0.1);
266+
r.x -= r.w;
267+
r.y -= r.h;
268+
for (btn, action) in self.action_btns.iter_mut().zip(&msg.actions) {
269+
btn.render_text(ui, r, t, &action.name, 0.5, false);
270+
ui.dy(-r.h - 0.01);
271+
}
272+
});
273+
274+
ui.dx(cr.x + pad + 0.01);
275+
ui.dy(cr.y + pad);
169276
let mw = cr.w - pad * 2. - 0.01;
170277
let mut h = 0.;
171278
macro_rules! dy {
@@ -193,6 +300,14 @@ impl Page for MessagePage {
193300
});
194301
}
195302
});
303+
self.sf.render(ui, t);
304+
if self.chart_task.is_some() {
305+
ui.full_loading_simple(t);
306+
}
196307
Ok(())
197308
}
309+
310+
fn next_scene(&mut self, s: &mut SharedState) -> prpr::scene::NextScene {
311+
self.sf.next_scene(s.t).unwrap_or_default()
312+
}
198313
}

0 commit comments

Comments
 (0)