use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use crate::{
backend::Backend,
project::Project,
templates::{self, TemplateContext},
};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AppleBackend {
#[serde(
default = "default_apple_project_path",
skip_serializing_if = "is_default_apple_project_path"
)]
pub project_path: PathBuf,
pub scheme: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub branch: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub revision: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub backend_path: Option<String>,
}
impl AppleBackend {
#[must_use]
pub fn new(scheme: impl Into<String>) -> Self {
Self {
project_path: default_apple_project_path(),
scheme: scheme.into(),
branch: None,
revision: None,
backend_path: None,
}
}
#[must_use]
pub fn with_project_path(mut self, path: impl Into<PathBuf>) -> Self {
self.project_path = path.into();
self
}
#[must_use]
pub fn with_backend_path(mut self, path: impl Into<String>) -> Self {
self.backend_path = Some(path.into());
self
}
#[must_use]
pub fn project_path(&self) -> &Path {
&self.project_path
}
}
fn default_apple_project_path() -> PathBuf {
PathBuf::from("apple")
}
fn is_default_apple_project_path(s: &Path) -> bool {
s == Path::new("apple")
}
impl Backend for AppleBackend {
const DEFAULT_PATH: &'static str = "apple";
fn path(&self) -> &Path {
&self.project_path
}
async fn init(project: &Project) -> Result<Self, crate::backend::FailToInitBackend> {
let manifest = project.manifest();
let is_playground =
manifest.package.package_type == crate::project::PackageType::Playground;
let (scheme, app_name, crate_name_for_template) = if is_playground {
(
"WaterUIApp".to_string(),
"WaterUIApp".to_string(),
"WaterUIApp".to_string(),
)
} else {
let crate_name = project.crate_name().to_string();
let app_name = crate_name
.split('-')
.map(|s| {
let mut chars = s.chars();
chars.next().map_or_else(String::new, |first| {
first.to_uppercase().chain(chars).collect()
})
})
.collect::<String>();
(crate_name.clone(), app_name, crate_name)
};
let backend_relative_path = project.backend_relative_path::<Self>();
let project_path = default_apple_project_path();
let ctx = TemplateContext {
app_display_name: manifest.package.name.clone(),
app_name,
crate_name: crate_name_for_template,
bundle_identifier: manifest.package.bundle_identifier.clone(),
author: String::new(),
android_backend_path: None,
use_remote_dev_backend: manifest.waterui_path.is_none(),
waterui_path: manifest.waterui_path.as_ref().map(PathBuf::from),
backend_project_path: Some(backend_relative_path),
android_permissions: Vec::new(),
};
templates::apple::scaffold(&project.backend_path::<Self>(), &ctx)
.await
.map_err(crate::backend::FailToInitBackend::Io)?;
Ok(Self {
project_path,
scheme,
branch: None,
revision: None,
backend_path: manifest.waterui_path.clone(),
})
}
}