diff --git a/src/elekf/api/auth/models.gleam b/src/elekf/api/auth/models.gleam index 53a77bd..f74f025 100644 --- a/src/elekf/api/auth/models.gleam +++ b/src/elekf/api/auth/models.gleam @@ -1,7 +1,9 @@ +/// Information of the logged in user. pub type User { User(id: Int, token: String, session_uuid: String) } +/// Information of the user's device. pub type Device { Device(name: String) } diff --git a/src/elekf/api/auth/storage.gleam b/src/elekf/api/auth/storage.gleam index 38622ca..40ab8de 100644 --- a/src/elekf/api/auth/storage.gleam +++ b/src/elekf/api/auth/storage.gleam @@ -1,3 +1,6 @@ +//// The auth storage stores the user's authentication credentials for future +//// use, i.e. when refreshing the page. + import gleam/dynamic import gleam/json import plinth/javascript/storage @@ -6,22 +9,27 @@ import elekf/api/auth/models const storage_key = "__elektrofoni_auth_storage" +/// Storage format of the authentication data in local storage. pub type StorageFormat { StorageFormat(user: models.User, device: models.Device) } +/// The local storage API used for storing authentication details. pub type AuthStorage = varasto.TypedStorage(StorageFormat) +/// Gets the `varasto` instance to use for reading and writing auth storage. pub fn get() { let assert Ok(local) = storage.local() varasto.new(local, reader(), writer()) } +/// Reads the previously stored value, if available. pub fn read(storage: AuthStorage) { varasto.get(storage, storage_key) } +/// Writes new value to the storage. pub fn write(storage: AuthStorage, data: StorageFormat) { varasto.set(storage, storage_key, data) } diff --git a/src/elekf/api/base_request_config.gleam b/src/elekf/api/base_request_config.gleam index 000921a..866e913 100644 --- a/src/elekf/api/base_request_config.gleam +++ b/src/elekf/api/base_request_config.gleam @@ -3,6 +3,7 @@ import ibroadcast/device_info.{DeviceInfo} import ibroadcast/request.{RequestConfig} import elekf/utils/navigator +/// Gets the base request config to use for all requests, authenticated and raw. pub fn base_request_config(device_name: String) { RequestConfig( app_info: elektrofoni.app_info, diff --git a/src/elekf/library.gleam b/src/elekf/library.gleam index a1393a6..6edf2ef 100644 --- a/src/elekf/library.gleam +++ b/src/elekf/library.gleam @@ -1,3 +1,5 @@ +//// The library stores the music library retrieved from iBroadcast. + import gleam/map.{Map} import elekf/library/track.{Track} import elekf/library/album.{Album} @@ -11,28 +13,34 @@ pub type Library { ) } +/// Gets an album from the library based on ID. pub fn get_album(library: Library, id: Int) { map.get(library.albums, id) } +/// Gets an artist from the library based on ID. pub fn get_artist(library: Library, id: Int) { map.get(library.artists, id) } +/// Gets a track from the library based on ID. pub fn get_track(library: Library, id: Int) { map.get(library.tracks, id) } +/// Gets an album from the library, asserting that it exists. pub fn assert_album(library: Library, id: Int) { let assert Ok(album) = map.get(library.albums, id) album } +/// Gets an artist from the library, asserting that it exists. pub fn assert_artist(library: Library, id: Int) { let assert Ok(artist) = map.get(library.artists, id) artist } +/// Gets a track from the library, asserting that it exists. pub fn assert_track(library: Library, id: Int) { let assert Ok(track) = map.get(library.tracks, id) track diff --git a/src/elekf/library/track.gleam b/src/elekf/library/track.gleam index 70630f8..47362ad 100644 --- a/src/elekf/library/track.gleam +++ b/src/elekf/library/track.gleam @@ -1,3 +1,7 @@ +/// A track in the music library. +/// +/// The `title_lower` contains the track title in lowercase, which is an +/// optimisation for searching. pub type Track { Track( number: Int, diff --git a/src/elekf/transfer/album.gleam b/src/elekf/transfer/album.gleam index 54fa5bf..4e44c32 100644 --- a/src/elekf/transfer/album.gleam +++ b/src/elekf/transfer/album.gleam @@ -1,6 +1,7 @@ import ibroadcast/library/library.{Album as APIAlbum} import elekf/library/album.{Album} +/// Converts API album response to library format. pub fn from(album: APIAlbum) { Album( name: album.name, diff --git a/src/elekf/transfer/artist.gleam b/src/elekf/transfer/artist.gleam index 0cb8dfc..a428066 100644 --- a/src/elekf/transfer/artist.gleam +++ b/src/elekf/transfer/artist.gleam @@ -1,6 +1,7 @@ import ibroadcast/library/library.{Artist as APIArtist} import elekf/library/artist.{Artist} +/// Converts API artist response to library format. pub fn from(artist: APIArtist) { Artist( name: artist.name, diff --git a/src/elekf/transfer/library.gleam b/src/elekf/transfer/library.gleam index 917b6d8..bc286f2 100644 --- a/src/elekf/transfer/library.gleam +++ b/src/elekf/transfer/library.gleam @@ -6,6 +6,7 @@ import elekf/transfer/album import elekf/transfer/artist import elekf/transfer/track +/// Converts API library response to library format. pub fn from(library: APILibrary) { let albums = transfer_map(library.albums, album.from) let artists = transfer_map(library.artists, artist.from) diff --git a/src/elekf/transfer/track.gleam b/src/elekf/transfer/track.gleam index 8545d3b..c0f81bf 100644 --- a/src/elekf/transfer/track.gleam +++ b/src/elekf/transfer/track.gleam @@ -2,6 +2,7 @@ import gleam/string import ibroadcast/library/library.{Track as APITrack} import elekf/library/track.{Track} +/// Converts API track response to library format. pub fn from(track: APITrack) { Track( number: track.number, diff --git a/src/elekf/utils/date.gleam b/src/elekf/utils/date.gleam index b622d2d..3631ffd 100644 --- a/src/elekf/utils/date.gleam +++ b/src/elekf/utils/date.gleam @@ -28,7 +28,7 @@ pub fn equals(a: Date, b: Date) -> Bool @external(javascript, "../../date_ffi.mjs", "bigger_than") pub fn bigger_than(a: Date, b: Date) -> Bool -/// Compare given dates, returning `Gt` if `a` > `b` +/// Compares given dates, returning `Gt` if `a` > `b` pub fn compare(a: Date, b: Date) -> Order { case equals(a, b) { True -> Eq @@ -41,6 +41,7 @@ pub fn compare(a: Date, b: Date) -> Order { } } +/// Decodes a dynamic value as an ISO 8601 formatted datetime string. pub fn decode(value: Dynamic) -> Result(Date, List(DecodeError)) { use str <- result.try(dynamic.string(value)) use date <- result.try( diff --git a/src/elekf/utils/http.gleam b/src/elekf/utils/http.gleam index 09cd861..9df52a8 100644 --- a/src/elekf/utils/http.gleam +++ b/src/elekf/utils/http.gleam @@ -4,9 +4,11 @@ import gleam/javascript/promise import ibroadcast/request as ibroadcast_request import ibroadcast/http as ibroadcast_http +/// Error returned by an HTTP request. pub type ResponseError = ibroadcast_request.ResponseError(fetch.FetchError) +/// Returns an HTTP request function based on `fetch`. pub fn requestor() -> ibroadcast_http.Requestor(fetch.FetchError) { fn(req: request.Request(String)) { use resp <- promise.try_await(fetch.send(req)) diff --git a/src/elekf/utils/navigator.gleam b/src/elekf/utils/navigator.gleam index dbc07b4..94e092a 100644 --- a/src/elekf/utils/navigator.gleam +++ b/src/elekf/utils/navigator.gleam @@ -1,2 +1,3 @@ +/// Returns the current browser's user agent. @external(javascript, "../../navigator_ffi.mjs", "userAgent") pub fn user_agent() -> String diff --git a/src/elekf/web/authed_view.gleam b/src/elekf/web/authed_view.gleam index 3ec1dcf..b79f576 100644 --- a/src/elekf/web/authed_view.gleam +++ b/src/elekf/web/authed_view.gleam @@ -1,3 +1,6 @@ +//// The authed view manages the user's request config and displays the base +//// view for the app. + import gleam/io import gleam/int import gleam/list diff --git a/src/elekf/web/common.gleam b/src/elekf/web/common.gleam index 2fd5bf0..2b0764b 100644 --- a/src/elekf/web/common.gleam +++ b/src/elekf/web/common.gleam @@ -1,9 +1,11 @@ import elekf/api/auth/models as auth_models +/// Authentication data for the user. pub type AuthData { AuthData(user: auth_models.User, device: auth_models.Device) } +/// Settings of the iBroadcast API. pub type Settings { Settings(artwork_server: String, streaming_server: String) } diff --git a/src/elekf/web/components/player.gleam b/src/elekf/web/components/player.gleam index 8e5eeb1..8cc490b 100644 --- a/src/elekf/web/components/player.gleam +++ b/src/elekf/web/components/player.gleam @@ -1,3 +1,5 @@ +//// The player view renders the media player UI element and its controls. + import gleam/list import gleam/uri import lustre/element.{text} diff --git a/src/elekf/web/components/search.gleam b/src/elekf/web/components/search.gleam index 79d3fb6..947d74e 100644 --- a/src/elekf/web/components/search.gleam +++ b/src/elekf/web/components/search.gleam @@ -1,3 +1,6 @@ +//// The search view renders a search bar, other views must do the searching +//// based on the emitted messages. + import lustre/element.{text} import lustre/element/html.{button, div, input} import lustre/attribute diff --git a/src/elekf/web/login_view.gleam b/src/elekf/web/login_view.gleam index 0b4d61f..1e7cf06 100644 --- a/src/elekf/web/login_view.gleam +++ b/src/elekf/web/login_view.gleam @@ -1,3 +1,5 @@ +//// The login view displays the login form and starts the login operation. + import gleam/string import gleam/javascript/promise import lustre/element.{text} diff --git a/src/elekf/web/main.gleam b/src/elekf/web/main.gleam index a36647a..1f88579 100644 --- a/src/elekf/web/main.gleam +++ b/src/elekf/web/main.gleam @@ -1,3 +1,5 @@ +//// The main view sets up everything and shows the login or authed view. + import gleam/io import gleam/option import lustre diff --git a/src/elekf/web/view.gleam b/src/elekf/web/view.gleam index 859cc5f..a6f8d3e 100644 --- a/src/elekf/web/view.gleam +++ b/src/elekf/web/view.gleam @@ -1,3 +1,4 @@ +/// Views that can be rendered on the main level. pub type View { LoginView AuthedView diff --git a/src/elektrofoni.gleam b/src/elektrofoni.gleam index a235d24..58b9bd8 100644 --- a/src/elektrofoni.gleam +++ b/src/elektrofoni.gleam @@ -1,13 +1,20 @@ import ibroadcast/app_info.{AppInfo} +/// Name of the application. pub const app_name = "elektrofoni" +/// Version of the application. pub const app_version = "1.0.0" +/// ID of the application. pub const app_id = 1098 +/// Constant app info to use in application. pub const app_info = AppInfo(app_name, app_version) +/// The bitrate to use for streaming by default. pub const bitrate = 256 +/// The expiry of the MP3 URLs generated for streaming, from the current moment +/// onwards, in milliseconds. pub const track_expiry_length = 10_800_000