• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #![allow(clippy::bool_assert_comparison)]
15 
16 const DOWNLOAD_FILE: &str = "request_agent_download_file\0";
17 const DOWNLOAD_SUCCESS: &str = "request_agent_download_success\0";
18 const DOWNLOAD_FAIL: &str = "request_agent_download_fail\0";
19 const UPLOAD_FILE: &str = "request_agent_upload_file\0";
20 const UPLOAD_SUCCESS: &str = "request_agent_upload_success\0";
21 const UPLOAD_FAIL: &str = "request_agent_upload_fail\0";
22 const TASK_COUNT: &str = "request_agent_task_count\0";
23 const DOWNLOAD_COMPLETE: &str = "request_agent_download_complete\0";
24 
25 use super::database::CustomizedNotification;
26 use super::ffi::{GetSystemResourceString, NotifyContent, ProgressCircle};
27 use super::notify_flow::{GroupProgress, ProgressNotify};
28 use crate::config::Action;
29 
progress_percentage(current: u64, total: u64) -> String30 fn progress_percentage(current: u64, total: u64) -> String {
31     if total == 0 {
32         return "100%".to_string();
33     }
34     format!(
35         "{}.{:02}%",
36         current * 100 / total,
37         current * 100 % total * 100 / total
38     )
39 }
40 
progress_size(current: u64) -> String41 fn progress_size(current: u64) -> String {
42     if current < 1024 {
43         format!("{}B", current)
44     } else if current < 1024 * 1024 {
45         format!("{:.2}KB", current as f64 / 1024.0)
46     } else if current < 1024 * 1024 * 1024 {
47         format!("{:.2}MB", current as f64 / 1024.0 / 1024.0)
48     } else {
49         format!("{:.2}GB", current as f64 / 1024.0 / 1024.0 / 1024.0)
50     }
51 }
52 
53 impl NotifyContent {
task_eventual_notify( mut customized: Option<CustomizedNotification>, action: Action, task_id: u32, uid: u32, file_name: String, is_successful: bool, ) -> Self54     pub(crate) fn task_eventual_notify(
55         mut customized: Option<CustomizedNotification>,
56         action: Action,
57         task_id: u32,
58         uid: u32,
59         file_name: String,
60         is_successful: bool,
61     ) -> Self {
62         let title = customized
63             .as_mut()
64             .and_then(|c| c.title.take())
65             .unwrap_or_else(|| match action {
66                 Action::Download => {
67                     if is_successful {
68                         GetSystemResourceString(DOWNLOAD_SUCCESS)
69                     } else {
70                         GetSystemResourceString(DOWNLOAD_FAIL)
71                     }
72                 }
73                 Action::Upload => {
74                     if is_successful {
75                         GetSystemResourceString(UPLOAD_SUCCESS)
76                     } else {
77                         GetSystemResourceString(UPLOAD_FAIL)
78                     }
79                 }
80                 _ => unreachable!(),
81             });
82         let text = customized.and_then(|c| c.text).unwrap_or(file_name);
83 
84         Self {
85             title,
86             text,
87             request_id: task_id,
88             uid,
89             live_view: false,
90             progress_circle: ProgressCircle::close(),
91             x_mark: false,
92         }
93     }
94 
task_progress_notify( mut customized: Option<CustomizedNotification>, info: &ProgressNotify, ) -> Self95     pub(crate) fn task_progress_notify(
96         mut customized: Option<CustomizedNotification>,
97         info: &ProgressNotify,
98     ) -> Self {
99         let title = customized
100             .as_mut()
101             .and_then(|c| c.title.take())
102             .unwrap_or_else(|| match info.action {
103                 Action::Download => {
104                     let title = GetSystemResourceString(DOWNLOAD_FILE);
105                     match info.total {
106                         Some(total) => {
107                             title.replace("%s", &progress_percentage(info.processed, total))
108                         }
109                         None => title.replace("%s", &progress_size(info.processed)),
110                     }
111                 }
112                 Action::Upload => {
113                     let title = GetSystemResourceString(UPLOAD_FILE);
114                     if let Some((current_count, total_count)) = info.multi_upload {
115                         title.replace("%s", &format!("{}/{}", current_count, total_count))
116                     } else {
117                         match info.total {
118                             Some(total) => {
119                                 title.replace("%s", &progress_percentage(info.processed, total))
120                             }
121                             None => title.replace("%s", &progress_size(info.processed)),
122                         }
123                     }
124                 }
125                 _ => unreachable!(),
126             });
127 
128         let text = customized
129             .and_then(|c| c.text.clone())
130             .unwrap_or_else(|| info.file_name.clone());
131 
132         let progress_circle = match info.total {
133             Some(total) => ProgressCircle::open(info.processed, total),
134             None => ProgressCircle::close(),
135         };
136 
137         Self {
138             title,
139             text,
140             request_id: info.task_id,
141             uid: info.uid as u32,
142             live_view: true,
143             progress_circle,
144             x_mark: true,
145         }
146     }
147 
group_eventual_notify( mut customized: Option<CustomizedNotification>, action: Action, group_id: u32, uid: u32, current_size: u64, successful_count: i32, failed_count: i32, ) -> Self148     pub(crate) fn group_eventual_notify(
149         mut customized: Option<CustomizedNotification>,
150         action: Action,
151         group_id: u32,
152         uid: u32,
153         current_size: u64,
154         successful_count: i32,
155         failed_count: i32,
156     ) -> Self {
157         let text_download_complete = GetSystemResourceString(DOWNLOAD_COMPLETE);
158         let text_download = text_download_complete.replace("%s", &progress_size(current_size).to_string());
159         let title = customized
160             .as_mut()
161             .and_then(|c| c.title.take())
162             .unwrap_or_else(|| match action {
163                 Action::Download => text_download,
164                 Action::Upload => format!("上传完成 {}", progress_size(current_size)),
165                 _ => unreachable!(),
166             });
167 
168         let text_task_count = GetSystemResourceString(TASK_COUNT);
169         let text_count = if text_task_count.contains("%d") {
170             text_task_count
171                 .replacen("%d", &successful_count.to_string(), 1)
172                 .replacen("%d", &failed_count.to_string(), 1)
173         } else {
174             text_task_count
175                 .replace("%1$d", &successful_count.to_string())
176                 .replace("%2$d", &failed_count.to_string())
177         };
178 
179         let text = customized
180             .and_then(|c| c.text)
181             .unwrap_or(text_count);
182 
183         Self {
184             title,
185             text,
186             request_id: group_id,
187             uid,
188             live_view: false,
189             progress_circle: ProgressCircle::close(),
190             x_mark: false,
191         }
192     }
193 
group_progress_notify( mut customized: Option<CustomizedNotification>, action: Action, group_id: u32, uid: u32, group_progress: &GroupProgress, ) -> Self194     pub(crate) fn group_progress_notify(
195         mut customized: Option<CustomizedNotification>,
196         action: Action,
197         group_id: u32,
198         uid: u32,
199         group_progress: &GroupProgress,
200     ) -> Self {
201         let title = customized
202             .as_mut()
203             .and_then(|c| c.title.take())
204             .unwrap_or_else(|| match action {
205                 Action::Download => {
206                     let title = GetSystemResourceString(DOWNLOAD_FILE);
207                     title.replace("%s", &progress_size(group_progress.processed()))
208                 }
209                 Action::Upload => {
210                     let title = GetSystemResourceString(UPLOAD_FILE);
211                     title.replace("%s", &progress_size(group_progress.processed()))
212                 }
213                 _ => unreachable!(),
214             });
215 
216         let (successful, failed) = (group_progress.successful(), group_progress.failed());
217         let text_task_count = GetSystemResourceString(TASK_COUNT);
218         let text_count = if text_task_count.contains("%d") {
219             text_task_count
220                 .replacen("%d", &successful.to_string(), 1)
221                 .replacen("%d", &failed.to_string(), 1)
222         } else {
223             text_task_count
224                 .replace("%1$d", &successful.to_string())
225                 .replace("%2$d", &failed.to_string())
226         };
227 
228         let text = customized
229             .and_then(|c| c.text)
230             .unwrap_or(text_count);
231 
232         let progress_circle =
233             ProgressCircle::open((successful + failed) as u64, group_progress.total() as u64);
234         Self {
235             title,
236             text,
237             request_id: group_id,
238             uid,
239             live_view: true,
240             progress_circle,
241             x_mark: false,
242         }
243     }
244 }
245 
246 impl ProgressCircle {
close() -> Self247     pub(crate) fn close() -> Self {
248         Self {
249             open: false,
250             current: 0,
251             total: 0,
252         }
253     }
open(mut current: u64, mut total: u64) -> Self254     pub(crate) fn open(mut current: u64, mut total: u64) -> Self {
255         while total > i32::MAX as u64 {
256             total >>= 1;
257             current >>= 1;
258         }
259         Self {
260             open: true,
261             current,
262             total,
263         }
264     }
265 }
266 
267 #[cfg(test)]
268 mod ut_typology {
269     include!("../../../tests/ut/service/notification_bar/ut_typology.rs");
270 }
271