Skip to content

Commit

Permalink
Begin to add domain modelling
Browse files Browse the repository at this point in the history
  • Loading branch information
NicoVIII committed Jun 9, 2022
1 parent b8958d0 commit 8a9a31e
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 90 deletions.
4 changes: 3 additions & 1 deletion src/Andromeda/AvaloniaApp/DomainTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ module DomainTypes =
open GogApi.DomainTypes
open Andromeda.Core

let toProductInfo game : ProductInfo = { id = game.id; title = game.name }
let toProductInfo game : ProductInfo =
{ id = game.id
title = game.name |> GameName.unwrap }
13 changes: 9 additions & 4 deletions src/Andromeda/AvaloniaApp/Update.fs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ module Update =
let sub dispatch =
match task with
| Some _ ->
"Download installer for " + game.name + "."
GameName.unwrap game.name
|> sprintf "Download installer for %s."
|> logInfo

let invoke () =
Expand All @@ -79,7 +80,8 @@ module Update =
DispatcherTimer.Run(Func<bool>(invoke), TimeSpan.FromSeconds 0.5)
|> ignore
| None ->
"Use cached installer for " + game.name + "."
GameName.unwrap game.name
|> sprintf "Use cached installer for %s."
|> logInfo

UpdateDownloadSize(game.id, maxFileSize)
Expand Down Expand Up @@ -136,7 +138,9 @@ module Update =
|> Cmd.ofMsg
| None ->
if showNotification then
AddNotification $"No new version available for %s{game.name}"
GameName.unwrap game.name
|> sprintf "No new version available for %s"
|> AddNotification
|> Cmd.ofMsg
else
Cmd.none
Expand Down Expand Up @@ -389,7 +393,8 @@ module Update =
state, Cmd.none
| _ ->
let invoke () =
Download.extractLibrary settings game.name filePath version
let gameName = GameName.unwrap game.name
Download.extractLibrary settings gameName filePath version

let cmd =
[ Cmd.ofMsg (UpdateDownloadInstalling game.id)
Expand Down
4 changes: 3 additions & 1 deletion src/Andromeda/AvaloniaApp/ViewComponents/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ open Avalonia.Layout
open SimpleOptics
open System

open Andromeda.Core

open Andromeda.AvaloniaApp

module Main =
Expand Down Expand Up @@ -37,7 +39,7 @@ module Main =
let gameName =
Optic.get (MainStateOptic.game productId) state
|> function
| Some game -> game.name
| Some game -> GameName.unwrap game.name
| None -> "<deleted>"

TabItem.create [
Expand Down
7 changes: 4 additions & 3 deletions src/Andromeda/Core/Andromeda.Core.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
<ItemGroup>
<Compile Include="Constants.fs" />
<Compile Include="Helpers/String.fs" />
<Compile Include="Helpers/Path.fs" />
<Compile Include="Helpers/IO.fs" />
<Compile Include="Types/Settings.fs" />
<Compile Include="Types/Game.fs" />
<Compile Include="Types/Game.Optics.fs" />
<Compile Include="Types/Domain.fs" />
<Compile Include="Types/Domain.Optics.fs" />
<Compile Include="Types/Domain.Modules.fs" />
<Compile Include="Types/Persistence.fs" />
<Compile Include="SystemInfo.fs" />
<Compile Include="System.fs" />
Expand Down
1 change: 1 addition & 0 deletions src/Andromeda/Core/Constants.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ module Constants =
let settingsFile = "settings.json"
let versionFile = "version.txt"
let installerCacheSubPath = "installers"
let tmpFolder = "tmp"
82 changes: 44 additions & 38 deletions src/Andromeda/Core/Download.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,60 @@ open Andromeda.Core.Helpers

/// A module for everything which helps to download and install games
module Download =
open System.Threading.Tasks

let client = new HttpClient()

let startFileDownload (SafeDownLink url) gameName version =
let version =
match version with
| Some v -> "-" + v
| None -> ""
type FileDownloadInfo =
{ downloadTask: Task<unit> option
filePath: string
tmpPath: string }

// Remove invalid characters from gameName
let gameName = Path.removeInvalidFileNameChars gameName
let getVersionSuffix =
function
| Some version -> $"-%s{version}"
| None -> ""

let getFileName gameName version =
let versionSuffix = getVersionSuffix version
sprintf "%s%s.%s" gameName versionSuffix SystemInfo.installerEnding

let buildFileDownload gameName version =
let dir = SystemInfo.installerCachePath
let fileName = getFileName gameName version
let filepath = Path.combine dir fileName
let tmppath = Path.combine3 dir Constants.tmpFolder fileName

let filepath =
Path.Combine(
dir,
sprintf "%s%s.%s" gameName version SystemInfo.installerEnding
)
{ downloadTask = None
filePath = filepath
tmpPath = tmppath }

let tmppath =
Path.Combine(
dir,
"tmp",
sprintf "%s%s.%s" gameName version SystemInfo.installerEnding
)
let setupDownloadTask (SafeDownLink url) path =
task {
use fileStream = File.create path

Directory.CreateDirectory(Path.Combine(dir, "tmp"))
|> ignore
let url = url.Replace("http://", "https://")

let file = FileInfo(filepath)
let! response = client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)

match file.Exists with
| false ->
let url = url.Replace("http://", "https://")
do response.EnsureSuccessStatusCode() |> ignore
do! response.Content.CopyToAsync fileStream
}

let startFileDownload downLink gameName version =
// Remove invalid characters from gameName
let gameName = Path.removeInvalidFileNameChars gameName

let task =
task {
use fileStream = File.Create tmppath
let download = buildFileDownload gameName version

let! response =
client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)
let file = FileInfo(download.filePath)

do response.EnsureSuccessStatusCode() |> ignore
do! response.Content.CopyToAsync fileStream
}
match file.Exists with
| false ->
let task = setupDownloadTask downLink download.tmpPath

(task |> Some, filepath, tmppath)
| true -> (None, filepath, tmppath)
{ download with downloadTask = Some task }
| true -> download

let rec copyDirectory
(sourceDirName: string)
Expand Down Expand Up @@ -222,17 +228,17 @@ module Download =
else
None

let (task, filepath, tmppath) =
let fileDownload =
startFileDownload
urlResponse.downlink
gameName
installer.version

return
Some(
task,
filepath,
tmppath,
fileDownload.downloadTask,
fileDownload.filePath,
fileDownload.tmpPath,
info.size * 1L<Byte>,
checksum
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,31 @@ namespace Andromeda.Core.Helpers
open System
open System.IO

[<RequireQualifiedAccess>]
module File =
let create path =
Path.GetDirectoryName(path: string)
|> Directory.CreateDirectory
|> ignore

File.Create(path)

[<RequireQualifiedAccess>]
module Path =
let combine path1 path2 = Path.Combine(path1, path2)
let combine3 path1 path2 path3 = Path.Combine(path1, path2, path3)

// Taken and converted to F# from https://blez.wordpress.com/2013/02/18/get-file-shortcuts-target-with-c/
let getShortcutTarget (file: string) =
try
if Path.GetExtension(file).ToLower().Equals(".lnk")
|> not then
if
Path.GetExtension(file).ToLower().Equals(".lnk")
|> not
then
Exception("Supplied file must be a .LNK file")
|> raise

let fileStream =
File.Open(file, FileMode.Open, FileAccess.Read)
let fileStream = File.Open(file, FileMode.Open, FileAccess.Read)

use fileReader = new BinaryReader(fileStream)

Expand Down Expand Up @@ -50,7 +63,7 @@ module Path =
- int64 (2) // read
// the base pathname. I don't need the 2 terminating nulls.
let linkTarget = fileReader.ReadChars((int) pathLength) // should be unicode safe
let link = new string(linkTarget)
let link = new string (linkTarget)

let start = link.IndexOf("\0\0")

Expand All @@ -64,7 +77,8 @@ module Path =
firstPart + secondPart
else
link
with _ -> ""
with
| _ -> ""

let removeInvalidFileNameChars part =
Path.GetInvalidFileNameChars()
Expand Down
29 changes: 29 additions & 0 deletions src/Andromeda/Core/Types/Domain.Modules.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace Andromeda.Core

[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GameName =
let create value = GameName value
let unwrap (GameName name) = name

[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module GamePath =
open Andromeda.Core.Helpers

let private create value = GamePath value

let ofName name =
name
|> GameName.unwrap
|> Path.removeInvalidFileNameChars
|> create

[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Game =
let create id name =
{ Game.id = id
name = GameName.create name
image = None
status = Pending }
19 changes: 19 additions & 0 deletions src/Andromeda/Core/Types/Domain.Optics.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Andromeda.Core

open SimpleOptics

[<RequireQualifiedAccess>]
module GameOptic =
let id = Lens((fun (x: Game) -> x.id), (fun game value -> { game with id = value }))

let name =
Lens((fun (x: Game) -> x.name), (fun game value -> { game with name = value }))

let image =
Lens((fun (x: Game) -> x.image), (fun game value -> { game with image = value }))

let status =
Lens(
(fun (x: Game) -> x.status),
(fun game value -> { game with status = value })
)
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,11 @@ type GameStatus =
| Installing of filepath: string
| Installed of version: string option * gameDir: string

type GameName = private GameName of string
type GamePath = private GamePath of string

type Game =
{ id: GogApi.DomainTypes.ProductId
name: string
name: GameName
image: string option
status: GameStatus }

module Game =
let create id name =
{ Game.id = id
name = name
image = None
status = Pending }
29 changes: 0 additions & 29 deletions src/Andromeda/Core/Types/Game.Optics.fs

This file was deleted.

0 comments on commit 8a9a31e

Please sign in to comment.