settings/night_mode/
night_mode_controller.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::night_mode_fidl_handler::Publisher;
6use crate::night_mode::types::NightModeInfo;
7use anyhow::Error;
8use fuchsia_async as fasync;
9use futures::channel::mpsc::UnboundedReceiver;
10use futures::channel::oneshot::Sender;
11use futures::StreamExt;
12use settings_common::inspect::event::{ResponseType, SettingValuePublisher};
13use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
14use settings_storage::storage_factory::{NoneT, StorageAccess, StorageFactory};
15use settings_storage::UpdateState;
16use std::rc::Rc;
17
18impl DeviceStorageCompatible for NightModeInfo {
19    type Loader = NoneT;
20    const KEY: &'static str = "night_mode_info";
21}
22
23impl StorageAccess for NightModeController {
24    type Storage = DeviceStorage;
25    type Data = NightModeInfo;
26    const STORAGE_KEY: &'static str = NightModeInfo::KEY;
27}
28
29#[derive(thiserror::Error, Debug)]
30pub(crate) enum NightModeError {
31    #[error("Write failed for NightMode: {0:?}")]
32    WriteFailure(Error),
33}
34
35impl From<&NightModeError> for ResponseType {
36    fn from(error: &NightModeError) -> Self {
37        match error {
38            NightModeError::WriteFailure(..) => ResponseType::StorageFailure,
39        }
40    }
41}
42
43pub(crate) enum Request {
44    Set(Option<bool>, Sender<Result<(), NightModeError>>),
45}
46
47pub struct NightModeController {
48    store: Rc<DeviceStorage>,
49    publisher: Option<Publisher>,
50    setting_value_publisher: SettingValuePublisher<NightModeInfo>,
51}
52
53impl NightModeController {
54    pub(super) async fn new<F>(
55        storage_factory: Rc<F>,
56        setting_value_publisher: SettingValuePublisher<NightModeInfo>,
57    ) -> Self
58    where
59        F: StorageFactory<Storage = DeviceStorage>,
60    {
61        NightModeController {
62            store: storage_factory.get_store().await,
63            publisher: None,
64            setting_value_publisher,
65        }
66    }
67
68    pub(super) fn register_publisher(&mut self, publisher: Publisher) {
69        self.publisher = Some(publisher);
70    }
71
72    fn publish(&self, info: NightModeInfo) {
73        let _ = self.setting_value_publisher.publish(&info);
74        if let Some(publisher) = self.publisher.as_ref() {
75            publisher.set(info);
76        }
77    }
78
79    pub(super) async fn handle(
80        self,
81        mut request_rx: UnboundedReceiver<Request>,
82    ) -> fasync::Task<()> {
83        fasync::Task::local(async move {
84            while let Some(request) = request_rx.next().await {
85                let Request::Set(night_mode_enabled, tx) = request;
86                let res = self.set(night_mode_enabled).await.map(|info| {
87                    if let Some(info) = info {
88                        self.publish(info);
89                    }
90                });
91                let _ = tx.send(res);
92            }
93        })
94    }
95
96    async fn set(
97        &self,
98        night_mode_enabled: Option<bool>,
99    ) -> Result<Option<NightModeInfo>, NightModeError> {
100        let mut info = self.store.get::<NightModeInfo>().await;
101        info.night_mode_enabled = night_mode_enabled;
102
103        self.store
104            .write(&info)
105            .await
106            .map(|state| (UpdateState::Updated == state).then_some(info))
107            .map_err(NightModeError::WriteFailure)
108    }
109
110    pub(super) async fn restore(&self) -> NightModeInfo {
111        self.store.get::<NightModeInfo>().await
112    }
113}