feat: compatibility info display in View Mod screen. log to ficsit-cli.log by default (#33)

* fix: log by default (ficsit-cli.log in CWD)

* chore: update readme with info on code generation

* chore: regenerate docs for default log file location

* feat: compatibility info state and note display. wip: keybind to switch view modes not working

* fix: move render code out to a function, but it still isn't quite working yet

* feat: display mod reference below mod name

* Fix compat toggle with

* Show scroll up/down on quick help

* chore: fix merge conflict

* chore: run go install mvdan.cc/gofumpt@latest; gofumpt -l -w .

* chore: run gci.exe write --skip-generated -s standard -s default -s 'prefix(github.com/satisfactorymodding/ficsit-cli)' -s blank -s dot .

* chore: update readme linting info and run golangci-lint --version

* fix: log file is defaulted to empty again

* fix(#33): update render to return just string

* fix(#33): renderModInfo returns only string

* fix(#33): reollback func namechange

* refactor(#33): remove redundant viewport refresh

* refactor(#33): update is not required after setting content

* refactor(#33): remove unrequired log

* docs(#33): update documentation to latest generated

* docs(#33): update cache reference to not contain username

* docs(#33): fix local dir references too

* refactor(#33): replace vague variable with more helpful

* Add directions about using dev schema when generate command fails

* Fix issues from earlier merge conflict

---------

Co-authored-by: Jack Stupple <jack.stupple@protonmail.com>
This commit is contained in:
Rob B 2023-12-27 18:32:56 -08:00 committed by GitHub
parent 0b2bc27119
commit e313efdfec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 534 additions and 253 deletions

View file

@ -90,6 +90,18 @@ Run `ficsit help` to see a list of available commands.
* [Go 1.21](https://go.dev/doc/install)
* IDE of Choice. Goland or VSCode suggested.
### Code Generation
If you update any of the GraphQL queries, run this to update generated code:
```bash
(echo "y") | npx graphqurl https://api.ficsit.app/v2/query --introspect -H 'content-type: application/json' > schema.graphql
go generate -tags tools -x ./...
```
If this command fails due to a mismatched schema,
you may need to use the url `https://api.ficsit.dev/v2/query` instead.
## Building
```bash
@ -97,3 +109,23 @@ go build
```
Will produce `ficsit-cli.exe` in the repo root directory.
### Linting
Install `golangci-lint` via the directions [here](https://golangci-lint.run/usage/install/#local-installation),
but make sure to install the version specified in `.github/workflows/push.yaml` instead of whatever it suggests.
Then, to run it, use:
```bash
golangci-lint run --fix
```
### Updating generated docs
The files within `./docs` are generated using cobra, use the following to update
them.
```bash
go run tools.go
```

View file

@ -40,7 +40,7 @@ func (l localDisk) Read(path string) ([]byte, error) {
}
func (l localDisk) Write(path string, data []byte) error {
return os.WriteFile(path, data, 0777) //nolint
return os.WriteFile(path, data, 0o777) //nolint
}
func (l localDisk) Remove(path string) error {
@ -48,7 +48,7 @@ func (l localDisk) Remove(path string) error {
}
func (l localDisk) MkDir(path string) error {
return os.MkdirAll(path, 0777) //nolint
return os.MkdirAll(path, 0o777) //nolint
}
func (l localDisk) ReadDir(path string) ([]Entry, error) {
@ -68,5 +68,5 @@ func (l localDisk) ReadDir(path string) ([]Entry, error) {
}
func (l localDisk) Open(path string, flag int) (io.WriteCloser, error) {
return os.OpenFile(path, flag, 0777) //nolint
return os.OpenFile(path, flag, 0o777) //nolint
}

View file

@ -7,7 +7,14 @@
// words - list of words to be always considered correct
"words": [
"ficsit",
"gofumpt",
"Goland",
"golangci",
"goquery",
"graphqurl",
"mvdan",
"pgdn",
"pgup",
"wordwrap"
],
// flagWords - list of words to be always considered incorrect

View file

@ -7,13 +7,13 @@ cli mod manager for satisfactory
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
-h, --help help for ficsit
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit apply [installation] ... [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit cli [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -13,12 +13,12 @@ Manage installations
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation add <path> [profile] [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation ls [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation remove <path> [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation set-profile <path> <profile> [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -13,12 +13,12 @@ Manage profiles
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile delete <name> [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile ls [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile mods <profile> [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile new <name> [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile rename <old> <name> [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -22,12 +22,12 @@ ficsit search [query] [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -13,12 +13,12 @@ Manage mods on SMR
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -19,12 +19,12 @@ ficsit smr upload [flags] <mod-id> <file> <changelog...>
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit version [flags]
```
--api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit")
--cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit")
--local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info")
--log-file string File to output logs to
--offline Whether to only use local data

View file

@ -11,6 +11,16 @@ query GetMod ($modId: String!) {
username
}
}
compatibility {
EA {
note
state
}
EXP {
note
state
}
}
full_description
source_url
created_at

View file

@ -46,6 +46,14 @@ type CheckVersionUploadStateStateCreateVersionResponseVersion struct {
// GetId returns CheckVersionUploadStateStateCreateVersionResponseVersion.Id, and is useful for accessing the field via an interface.
func (v *CheckVersionUploadStateStateCreateVersionResponseVersion) GetId() string { return v.Id }
type CompatibilityState string
const (
CompatibilityStateWorks CompatibilityState = "Works"
CompatibilityStateDamaged CompatibilityState = "Damaged"
CompatibilityStateBroken CompatibilityState = "Broken"
)
// CreateVersionResponse is returned by CreateVersion on success.
type CreateVersionResponse struct {
VersionID string `json:"versionID"`
@ -64,15 +72,16 @@ func (v *FinalizeCreateVersionResponse) GetSuccess() bool { return v.Success }
// GetModMod includes the requested fields of the GraphQL type Mod.
type GetModMod struct {
Id string `json:"id"`
Mod_reference string `json:"mod_reference"`
Name string `json:"name"`
Views int `json:"views"`
Downloads int `json:"downloads"`
Authors []GetModModAuthorsUserMod `json:"authors"`
Full_description string `json:"full_description"`
Source_url string `json:"source_url"`
Created_at time.Time `json:"-"`
Id string `json:"id"`
Mod_reference string `json:"mod_reference"`
Name string `json:"name"`
Views int `json:"views"`
Downloads int `json:"downloads"`
Authors []GetModModAuthorsUserMod `json:"authors"`
Compatibility GetModModCompatibilityCompatibilityInfo `json:"compatibility"`
Full_description string `json:"full_description"`
Source_url string `json:"source_url"`
Created_at time.Time `json:"-"`
}
// GetId returns GetModMod.Id, and is useful for accessing the field via an interface.
@ -93,6 +102,11 @@ func (v *GetModMod) GetDownloads() int { return v.Downloads }
// GetAuthors returns GetModMod.Authors, and is useful for accessing the field via an interface.
func (v *GetModMod) GetAuthors() []GetModModAuthorsUserMod { return v.Authors }
// GetCompatibility returns GetModMod.Compatibility, and is useful for accessing the field via an interface.
func (v *GetModMod) GetCompatibility() GetModModCompatibilityCompatibilityInfo {
return v.Compatibility
}
// GetFull_description returns GetModMod.Full_description, and is useful for accessing the field via an interface.
func (v *GetModMod) GetFull_description() string { return v.Full_description }
@ -128,7 +142,7 @@ func (v *GetModMod) UnmarshalJSON(b []byte) error {
src, dst)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal GetModMod.Created_at: %w", err)
"unable to unmarshal GetModMod.Created_at: %w", err)
}
}
}
@ -148,6 +162,8 @@ type __premarshalGetModMod struct {
Authors []GetModModAuthorsUserMod `json:"authors"`
Compatibility GetModModCompatibilityCompatibilityInfo `json:"compatibility"`
Full_description string `json:"full_description"`
Source_url string `json:"source_url"`
@ -172,6 +188,7 @@ func (v *GetModMod) __premarshalJSON() (*__premarshalGetModMod, error) {
retval.Views = v.Views
retval.Downloads = v.Downloads
retval.Authors = v.Authors
retval.Compatibility = v.Compatibility
retval.Full_description = v.Full_description
retval.Source_url = v.Source_url
{
@ -183,7 +200,7 @@ func (v *GetModMod) __premarshalJSON() (*__premarshalGetModMod, error) {
&src)
if err != nil {
return nil, fmt.Errorf(
"Unable to marshal GetModMod.Created_at: %w", err)
"unable to marshal GetModMod.Created_at: %w", err)
}
}
return &retval, nil
@ -209,6 +226,50 @@ type GetModModAuthorsUserModUser struct {
// GetUsername returns GetModModAuthorsUserModUser.Username, and is useful for accessing the field via an interface.
func (v *GetModModAuthorsUserModUser) GetUsername() string { return v.Username }
// GetModModCompatibilityCompatibilityInfo includes the requested fields of the GraphQL type CompatibilityInfo.
type GetModModCompatibilityCompatibilityInfo struct {
EA GetModModCompatibilityCompatibilityInfoEACompatibility `json:"EA"`
EXP GetModModCompatibilityCompatibilityInfoEXPCompatibility `json:"EXP"`
}
// GetEA returns GetModModCompatibilityCompatibilityInfo.EA, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfo) GetEA() GetModModCompatibilityCompatibilityInfoEACompatibility {
return v.EA
}
// GetEXP returns GetModModCompatibilityCompatibilityInfo.EXP, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfo) GetEXP() GetModModCompatibilityCompatibilityInfoEXPCompatibility {
return v.EXP
}
// GetModModCompatibilityCompatibilityInfoEACompatibility includes the requested fields of the GraphQL type Compatibility.
type GetModModCompatibilityCompatibilityInfoEACompatibility struct {
Note string `json:"note"`
State CompatibilityState `json:"state"`
}
// GetNote returns GetModModCompatibilityCompatibilityInfoEACompatibility.Note, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEACompatibility) GetNote() string { return v.Note }
// GetState returns GetModModCompatibilityCompatibilityInfoEACompatibility.State, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEACompatibility) GetState() CompatibilityState {
return v.State
}
// GetModModCompatibilityCompatibilityInfoEXPCompatibility includes the requested fields of the GraphQL type Compatibility.
type GetModModCompatibilityCompatibilityInfoEXPCompatibility struct {
Note string `json:"note"`
State CompatibilityState `json:"state"`
}
// GetNote returns GetModModCompatibilityCompatibilityInfoEXPCompatibility.Note, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEXPCompatibility) GetNote() string { return v.Note }
// GetState returns GetModModCompatibilityCompatibilityInfoEXPCompatibility.State, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEXPCompatibility) GetState() CompatibilityState {
return v.State
}
// GetModNameMod includes the requested fields of the GraphQL type Mod.
type GetModNameMod struct {
Id string `json:"id"`
@ -245,51 +306,51 @@ type ModFields string
const (
ModFieldsCreatedAt ModFields = "created_at"
ModFieldsUpdatedAt ModFields = "updated_at"
ModFieldsName ModFields = "name"
ModFieldsViews ModFields = "views"
ModFieldsDownloads ModFields = "downloads"
ModFieldsHotness ModFields = "hotness"
ModFieldsLastVersionDate ModFields = "last_version_date"
ModFieldsName ModFields = "name"
ModFieldsPopularity ModFields = "popularity"
ModFieldsLastVersionDate ModFields = "last_version_date"
ModFieldsSearch ModFields = "search"
ModFieldsUpdatedAt ModFields = "updated_at"
ModFieldsViews ModFields = "views"
)
type ModFilter struct {
Hidden bool `json:"hidden,omitempty"`
Ids []string `json:"ids,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
Order Order `json:"order,omitempty"`
Order_by ModFields `json:"order_by,omitempty"`
References []string `json:"references,omitempty"`
Order Order `json:"order,omitempty"`
Search string `json:"search,omitempty"`
Ids []string `json:"ids,omitempty"`
References []string `json:"references,omitempty"`
Hidden bool `json:"hidden,omitempty"`
TagIDs []string `json:"tagIDs,omitempty"`
}
// GetHidden returns ModFilter.Hidden, and is useful for accessing the field via an interface.
func (v *ModFilter) GetHidden() bool { return v.Hidden }
// GetIds returns ModFilter.Ids, and is useful for accessing the field via an interface.
func (v *ModFilter) GetIds() []string { return v.Ids }
// GetLimit returns ModFilter.Limit, and is useful for accessing the field via an interface.
func (v *ModFilter) GetLimit() int { return v.Limit }
// GetOffset returns ModFilter.Offset, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOffset() int { return v.Offset }
// GetOrder_by returns ModFilter.Order_by, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOrder_by() ModFields { return v.Order_by }
// GetOrder returns ModFilter.Order, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOrder() Order { return v.Order }
// GetOrder_by returns ModFilter.Order_by, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOrder_by() ModFields { return v.Order_by }
// GetSearch returns ModFilter.Search, and is useful for accessing the field via an interface.
func (v *ModFilter) GetSearch() string { return v.Search }
// GetIds returns ModFilter.Ids, and is useful for accessing the field via an interface.
func (v *ModFilter) GetIds() []string { return v.Ids }
// GetReferences returns ModFilter.References, and is useful for accessing the field via an interface.
func (v *ModFilter) GetReferences() []string { return v.References }
// GetSearch returns ModFilter.Search, and is useful for accessing the field via an interface.
func (v *ModFilter) GetSearch() string { return v.Search }
// GetHidden returns ModFilter.Hidden, and is useful for accessing the field via an interface.
func (v *ModFilter) GetHidden() bool { return v.Hidden }
// GetTagIDs returns ModFilter.TagIDs, and is useful for accessing the field via an interface.
func (v *ModFilter) GetTagIDs() []string { return v.TagIDs }
@ -503,7 +564,7 @@ func (v *ModsModsGetModsModsMod) UnmarshalJSON(b []byte) error {
src, dst)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal ModsModsGetModsModsMod.Last_version_date: %w", err)
"unable to unmarshal ModsModsGetModsModsMod.Last_version_date: %w", err)
}
}
}
@ -516,7 +577,7 @@ func (v *ModsModsGetModsModsMod) UnmarshalJSON(b []byte) error {
src, dst)
if err != nil {
return fmt.Errorf(
"Unable to unmarshal ModsModsGetModsModsMod.Created_at: %w", err)
"unable to unmarshal ModsModsGetModsModsMod.Created_at: %w", err)
}
}
}
@ -566,7 +627,7 @@ func (v *ModsModsGetModsModsMod) __premarshalJSON() (*__premarshalModsModsGetMod
&src)
if err != nil {
return nil, fmt.Errorf(
"Unable to marshal ModsModsGetModsModsMod.Last_version_date: %w", err)
"unable to marshal ModsModsGetModsModsMod.Last_version_date: %w", err)
}
}
{
@ -578,7 +639,7 @@ func (v *ModsModsGetModsModsMod) __premarshalJSON() (*__premarshalModsModsGetMod
&src)
if err != nil {
return nil, fmt.Errorf(
"Unable to marshal ModsModsGetModsModsMod.Created_at: %w", err)
"unable to marshal ModsModsGetModsModsMod.Created_at: %w", err)
}
}
retval.Views = v.Views
@ -683,46 +744,46 @@ func (v *SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersionTargetsSMLVer
type TargetName string
const (
TargetNameLinuxserver TargetName = "LinuxServer"
TargetNameWindows TargetName = "Windows"
TargetNameWindowsserver TargetName = "WindowsServer"
TargetNameLinuxserver TargetName = "LinuxServer"
)
type VersionFields string
const (
VersionFieldsCreatedAt VersionFields = "created_at"
VersionFieldsDownloads VersionFields = "downloads"
VersionFieldsUpdatedAt VersionFields = "updated_at"
VersionFieldsDownloads VersionFields = "downloads"
)
type VersionFilter struct {
Ids []string `json:"ids,omitempty"`
Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"`
Order Order `json:"order,omitempty"`
Order_by VersionFields `json:"order_by,omitempty"`
Order Order `json:"order,omitempty"`
Search string `json:"search,omitempty"`
Ids []string `json:"ids,omitempty"`
}
// GetIds returns VersionFilter.Ids, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetIds() []string { return v.Ids }
// GetLimit returns VersionFilter.Limit, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetLimit() int { return v.Limit }
// GetOffset returns VersionFilter.Offset, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOffset() int { return v.Offset }
// GetOrder returns VersionFilter.Order, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOrder() Order { return v.Order }
// GetOrder_by returns VersionFilter.Order_by, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOrder_by() VersionFields { return v.Order_by }
// GetOrder returns VersionFilter.Order, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOrder() Order { return v.Order }
// GetSearch returns VersionFilter.Search, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetSearch() string { return v.Search }
// GetIds returns VersionFilter.Ids, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetIds() []string { return v.Ids }
// VersionMod includes the requested fields of the GraphQL type Mod.
type VersionMod struct {
Id string `json:"id"`
@ -863,15 +924,8 @@ func (v *__VersionInput) GetModId() string { return v.ModId }
// GetVersion returns __VersionInput.Version, and is useful for accessing the field via an interface.
func (v *__VersionInput) GetVersion() string { return v.Version }
func CheckVersionUploadState(
ctx context.Context,
client graphql.Client,
modId string,
versionId string,
) (*CheckVersionUploadStateResponse, error) {
req := &graphql.Request{
OpName: "CheckVersionUploadState",
Query: `
// The query or mutation executed by CheckVersionUploadState.
const CheckVersionUploadState_Operation = `
query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) {
state: checkVersionUploadState(modId: $modId, versionId: $versionId) {
auto_approved
@ -880,7 +934,17 @@ query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) {
}
}
}
`,
`
func CheckVersionUploadState(
ctx context.Context,
client graphql.Client,
modId string,
versionId string,
) (*CheckVersionUploadStateResponse, error) {
req := &graphql.Request{
OpName: "CheckVersionUploadState",
Query: CheckVersionUploadState_Operation,
Variables: &__CheckVersionUploadStateInput{
ModId: modId,
VersionId: versionId,
@ -900,6 +964,13 @@ query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) {
return &data, err
}
// The query or mutation executed by CreateVersion.
const CreateVersion_Operation = `
mutation CreateVersion ($modId: ModID!) {
versionID: createVersion(modId: $modId)
}
`
func CreateVersion(
ctx context.Context,
client graphql.Client,
@ -907,11 +978,7 @@ func CreateVersion(
) (*CreateVersionResponse, error) {
req := &graphql.Request{
OpName: "CreateVersion",
Query: `
mutation CreateVersion ($modId: ModID!) {
versionID: createVersion(modId: $modId)
}
`,
Query: CreateVersion_Operation,
Variables: &__CreateVersionInput{
ModId: modId,
},
@ -930,6 +997,13 @@ mutation CreateVersion ($modId: ModID!) {
return &data, err
}
// The query or mutation executed by FinalizeCreateVersion.
const FinalizeCreateVersion_Operation = `
mutation FinalizeCreateVersion ($modId: ModID!, $versionId: VersionID!, $version: NewVersion!) {
success: finalizeCreateVersion(modId: $modId, versionId: $versionId, version: $version)
}
`
func FinalizeCreateVersion(
ctx context.Context,
client graphql.Client,
@ -939,11 +1013,7 @@ func FinalizeCreateVersion(
) (*FinalizeCreateVersionResponse, error) {
req := &graphql.Request{
OpName: "FinalizeCreateVersion",
Query: `
mutation FinalizeCreateVersion ($modId: ModID!, $versionId: VersionID!, $version: NewVersion!) {
success: finalizeCreateVersion(modId: $modId, versionId: $versionId, version: $version)
}
`,
Query: FinalizeCreateVersion_Operation,
Variables: &__FinalizeCreateVersionInput{
ModId: modId,
VersionId: versionId,
@ -964,14 +1034,8 @@ mutation FinalizeCreateVersion ($modId: ModID!, $versionId: VersionID!, $version
return &data, err
}
func GetMod(
ctx context.Context,
client graphql.Client,
modId string,
) (*GetModResponse, error) {
req := &graphql.Request{
OpName: "GetMod",
Query: `
// The query or mutation executed by GetMod.
const GetMod_Operation = `
query GetMod ($modId: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) {
id
@ -985,12 +1049,31 @@ query GetMod ($modId: String!) {
username
}
}
compatibility {
EA {
note
state
}
EXP {
note
state
}
}
full_description
source_url
created_at
}
}
`,
`
func GetMod(
ctx context.Context,
client graphql.Client,
modId string,
) (*GetModResponse, error) {
req := &graphql.Request{
OpName: "GetMod",
Query: GetMod_Operation,
Variables: &__GetModInput{
ModId: modId,
},
@ -1009,14 +1092,8 @@ query GetMod ($modId: String!) {
return &data, err
}
func GetModName(
ctx context.Context,
client graphql.Client,
modId string,
) (*GetModNameResponse, error) {
req := &graphql.Request{
OpName: "GetModName",
Query: `
// The query or mutation executed by GetModName.
const GetModName_Operation = `
query GetModName ($modId: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) {
id
@ -1024,7 +1101,16 @@ query GetModName ($modId: String!) {
name
}
}
`,
`
func GetModName(
ctx context.Context,
client graphql.Client,
modId string,
) (*GetModNameResponse, error) {
req := &graphql.Request{
OpName: "GetModName",
Query: GetModName_Operation,
Variables: &__GetModNameInput{
ModId: modId,
},
@ -1043,15 +1129,8 @@ query GetModName ($modId: String!) {
return &data, err
}
func ModVersions(
ctx context.Context,
client graphql.Client,
modId string,
filter VersionFilter,
) (*ModVersionsResponse, error) {
req := &graphql.Request{
OpName: "ModVersions",
Query: `
// The query or mutation executed by ModVersions.
const ModVersions_Operation = `
query ModVersions ($modId: String!, $filter: VersionFilter) {
mod: getModByIdOrReference(modIdOrReference: $modId) {
id
@ -1061,7 +1140,17 @@ query ModVersions ($modId: String!, $filter: VersionFilter) {
}
}
}
`,
`
func ModVersions(
ctx context.Context,
client graphql.Client,
modId string,
filter VersionFilter,
) (*ModVersionsResponse, error) {
req := &graphql.Request{
OpName: "ModVersions",
Query: ModVersions_Operation,
Variables: &__ModVersionsInput{
ModId: modId,
Filter: filter,
@ -1081,14 +1170,8 @@ query ModVersions ($modId: String!, $filter: VersionFilter) {
return &data, err
}
func ModVersionsWithDependencies(
ctx context.Context,
client graphql.Client,
modId string,
) (*ModVersionsWithDependenciesResponse, error) {
req := &graphql.Request{
OpName: "ModVersionsWithDependencies",
Query: `
// The query or mutation executed by ModVersionsWithDependencies.
const ModVersionsWithDependencies_Operation = `
query ModVersionsWithDependencies ($modId: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) {
id
@ -1110,7 +1193,16 @@ query ModVersionsWithDependencies ($modId: String!) {
}
}
}
`,
`
func ModVersionsWithDependencies(
ctx context.Context,
client graphql.Client,
modId string,
) (*ModVersionsWithDependenciesResponse, error) {
req := &graphql.Request{
OpName: "ModVersionsWithDependencies",
Query: ModVersionsWithDependencies_Operation,
Variables: &__ModVersionsWithDependenciesInput{
ModId: modId,
},
@ -1129,14 +1221,8 @@ query ModVersionsWithDependencies ($modId: String!) {
return &data, err
}
func Mods(
ctx context.Context,
client graphql.Client,
filter ModFilter,
) (*ModsResponse, error) {
req := &graphql.Request{
OpName: "Mods",
Query: `
// The query or mutation executed by Mods.
const Mods_Operation = `
query Mods ($filter: ModFilter) {
mods: getMods(filter: $filter) {
count
@ -1153,7 +1239,16 @@ query Mods ($filter: ModFilter) {
}
}
}
`,
`
func Mods(
ctx context.Context,
client graphql.Client,
filter ModFilter,
) (*ModsResponse, error) {
req := &graphql.Request{
OpName: "Mods",
Query: Mods_Operation,
Variables: &__ModsInput{
Filter: filter,
},
@ -1172,13 +1267,8 @@ query Mods ($filter: ModFilter) {
return &data, err
}
func SMLVersions(
ctx context.Context,
client graphql.Client,
) (*SMLVersionsResponse, error) {
req := &graphql.Request{
OpName: "SMLVersions",
Query: `
// The query or mutation executed by SMLVersions.
const SMLVersions_Operation = `
query SMLVersions {
smlVersions: getSMLVersions(filter: {limit:100}) {
count
@ -1193,7 +1283,15 @@ query SMLVersions {
}
}
}
`,
`
func SMLVersions(
ctx context.Context,
client graphql.Client,
) (*SMLVersionsResponse, error) {
req := &graphql.Request{
OpName: "SMLVersions",
Query: SMLVersions_Operation,
}
var err error
@ -1209,15 +1307,8 @@ query SMLVersions {
return &data, err
}
func Version(
ctx context.Context,
client graphql.Client,
modId string,
version string,
) (*VersionResponse, error) {
req := &graphql.Request{
OpName: "Version",
Query: `
// The query or mutation executed by Version.
const Version_Operation = `
query Version ($modId: String!, $version: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) {
id
@ -1229,7 +1320,17 @@ query Version ($modId: String!, $version: String!) {
}
}
}
`,
`
func Version(
ctx context.Context,
client graphql.Client,
modId string,
version string,
) (*VersionResponse, error) {
req := &graphql.Request{
OpName: "Version",
Query: Version_Operation,
Variables: &__VersionInput{
ModId: modId,
Version: version,

View file

@ -1,5 +1,7 @@
package mods
// cspell:disable
import (
"context"
"log/slog"
@ -23,40 +25,46 @@ import (
"github.com/satisfactorymodding/ficsit-cli/tea/utils"
)
// cspell:enable
var _ tea.Model = (*modVersionMenu)(nil)
type modInfo struct {
root components.RootModel
parent tea.Model
modData chan ficsit.GetModMod
modError chan string
error *components.ErrorComponent
help help.Model
keys modInfoKeyMap
viewport viewport.Model
spinner spinner.Model
ready bool
root components.RootModel
parent tea.Model
modData chan ficsit.GetModMod
modDataCache ficsit.GetModMod
modError chan string
error *components.ErrorComponent
help help.Model
keys modInfoKeyMap
viewport viewport.Model
spinner spinner.Model
ready bool
compatViewMode bool
}
type modInfoKeyMap struct {
Up key.Binding
UpHalf key.Binding
UpPage key.Binding
Down key.Binding
DownHalf key.Binding
DownPage key.Binding
Help key.Binding
Back key.Binding
Up key.Binding
UpHalf key.Binding
UpPage key.Binding
Down key.Binding
DownHalf key.Binding
DownPage key.Binding
Help key.Binding
Back key.Binding
CompatInfo key.Binding
}
func (k modInfoKeyMap) ShortHelp() []key.Binding {
return []key.Binding{k.Help, k.Back}
return []key.Binding{k.Help, k.Back, k.Up, k.Down, k.CompatInfo}
}
func (k modInfoKeyMap) FullHelp() [][]key.Binding {
return [][]key.Binding{
{k.Up, k.UpHalf, k.UpPage},
{k.Down, k.DownHalf, k.DownPage},
{k.CompatInfo},
{k.Help, k.Back},
}
}
@ -72,14 +80,15 @@ func NewModInfo(root components.RootModel, parent tea.Model, mod utils.Mod) tea.
ready: false,
help: help.New(),
keys: modInfoKeyMap{
Up: key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "move up")),
UpHalf: key.NewBinding(key.WithKeys("u"), key.WithHelp("u", "up half page")),
UpPage: key.NewBinding(key.WithKeys("pgup", "b"), key.WithHelp("pgup/b", "page up")),
Down: key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "move down")),
DownHalf: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "down half page")),
DownPage: key.NewBinding(key.WithKeys("pgdn", "f"), key.WithHelp("pgdn/f", "page down")),
Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "toggle help")),
Back: key.NewBinding(key.WithKeys("q"), key.WithHelp("q", "back")),
Up: key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "move up")),
UpHalf: key.NewBinding(key.WithKeys("u"), key.WithHelp("u", "up half page")),
UpPage: key.NewBinding(key.WithKeys("pgup", "b"), key.WithHelp("pgup/b", "page up")),
Down: key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "move down")),
DownHalf: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "down half page")),
DownPage: key.NewBinding(key.WithKeys("pgdn", "f"), key.WithHelp("pgdn/f", "page down")),
Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "toggle help")),
Back: key.NewBinding(key.WithKeys("q"), key.WithHelp("q", "back")),
CompatInfo: key.NewBinding(key.WithKeys("i"), key.WithHelp("i", "toggle compatibility info view")),
},
}
@ -144,13 +153,19 @@ func (m modInfo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Quit
case "?":
m.help.ShowAll = !m.help.ShowAll
newModel, cmd := m.CalculateSizes(m.root.Size())
return newModel, cmd
return m.CalculateSizes(m.root.Size())
case "i":
m.compatViewMode = !m.compatViewMode
m.viewport = m.newViewport()
m.viewport.SetContent(m.renderModInfo())
return m.CalculateSizes(m.root.Size())
default:
var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg)
return m, cmd
break
}
var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg)
return m, cmd
case tea.WindowSizeMsg:
return m.CalculateSizes(msg)
case spinner.TickMsg:
@ -160,67 +175,121 @@ func (m modInfo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case utils.TickMsg:
select {
case mod := <-m.modData:
bottomPadding := 2
if m.help.ShowAll {
bottomPadding = 4
}
top, right, bottom, left := lipgloss.NewStyle().Margin(m.root.Height(), 3, bottomPadding).GetMargin()
m.viewport = viewport.Model{Width: m.root.Size().Width - left - right, Height: m.root.Size().Height - top - bottom}
title := lipgloss.NewStyle().Padding(0, 2).Render(utils.TitleStyle.Render(mod.Name)) + "\n"
sidebar := ""
sidebar += utils.LabelStyle.Render("Views: ") + strconv.Itoa(mod.Views) + "\n"
sidebar += utils.LabelStyle.Render("Downloads: ") + strconv.Itoa(mod.Downloads) + "\n"
sidebar += "\n"
sidebar += utils.LabelStyle.Render("Authors:") + "\n"
for _, author := range mod.Authors {
sidebar += "\n"
sidebar += utils.LabelStyle.Render(author.User.Username) + " - " + author.Role
}
converter := md.NewConverter("", true, nil)
converter.AddRules(md.Rule{
Filter: []string{"#text"},
Replacement: func(content string, selec *goquery.Selection, options *md.Options) *string {
text := selec.Text()
return &text
},
})
markdownDescription, err := converter.ConvertString(mod.Full_description)
if err != nil {
slog.Error("failed to convert html to markdown", slog.Any("err", err))
markdownDescription = mod.Full_description
}
description, err := glamour.Render(markdownDescription, "dark")
if err != nil {
slog.Error("failed to render markdown", slog.Any("err", err))
description = mod.Full_description
}
bottomPart := lipgloss.JoinHorizontal(lipgloss.Top, sidebar, strings.TrimSpace(description))
m.viewport.SetContent(lipgloss.JoinVertical(lipgloss.Left, title, bottomPart))
var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg)
return m, cmd
m.modDataCache = mod
m.viewport = m.newViewport()
m.viewport.SetContent(m.renderModInfo())
break
case err := <-m.modError:
errorComponent, cmd := components.NewErrorComponent(err, time.Second*5)
errorComponent, _ := components.NewErrorComponent(err, time.Second*5)
m.error = errorComponent
return m, cmd
break
default:
return m, utils.Ticker()
// skip
break
}
return m, utils.Ticker()
}
return m, nil
}
func (m modInfo) newViewport() viewport.Model {
bottomPadding := 2
if m.help.ShowAll {
bottomPadding = 4
}
top, right, bottom, left := lipgloss.NewStyle().Margin(m.root.Height(), 3, bottomPadding).GetMargin()
return viewport.Model{Width: m.root.Size().Width - left - right, Height: m.root.Size().Height - top - bottom}
}
func (m modInfo) renderModInfo() string {
mod := m.modDataCache
title := lipgloss.NewStyle().Padding(0, 2).Render(utils.TitleStyle.Render(mod.Name)) + "\n"
title += lipgloss.NewStyle().Padding(0, 3).Render("("+string(mod.Mod_reference)+")") + "\n"
sidebar := ""
sidebar += utils.LabelStyle.Render("Views: ") + strconv.Itoa(mod.Views) + "\n"
sidebar += utils.LabelStyle.Render("Downloads: ") + strconv.Itoa(mod.Downloads) + "\n"
sidebar += "\n"
sidebar += utils.LabelStyle.Render("EA Compat: ") + m.renderCompatInfo(mod.Compatibility.EA.State) + "\n"
sidebar += utils.LabelStyle.Render("EXP Compat: ") + m.renderCompatInfo(mod.Compatibility.EXP.State) + "\n"
sidebar += "\n"
sidebar += utils.LabelStyle.Render("Authors:") + "\n"
converter := md.NewConverter("", true, nil)
converter.AddRules(md.Rule{
Filter: []string{"#text"},
Replacement: func(content string, selection *goquery.Selection, options *md.Options) *string {
text := selection.Text()
return &text
},
})
for _, author := range mod.Authors {
sidebar += "\n"
sidebar += utils.LabelStyle.Render(author.User.Username) + " - " + author.Role
}
description := ""
if m.compatViewMode {
a := ""
a += "Compatibility information is maintained by the community." + "\n"
a += "If you encounter issues with a mod, please report it on the Discord." + "\n"
a += "Learn more about what compatibility states mean on ficsit.app" + "\n\n"
description = m.renderDescriptionText(a, converter)
description += " " + utils.TitleStyle.Render("Early Access Branch Compatibility Note") + "\n"
description += m.renderDescriptionText(mod.Compatibility.EA.Note, converter)
description += "\n\n"
description += " " + utils.TitleStyle.Render("Experimental Branch Compatibility Note") + "\n"
description += m.renderDescriptionText(mod.Compatibility.EXP.Note, converter)
} else {
description += m.renderDescriptionText(mod.Full_description, converter)
}
bottomPart := lipgloss.JoinHorizontal(lipgloss.Top, sidebar, strings.TrimSpace(description))
return lipgloss.JoinVertical(lipgloss.Left, title, bottomPart)
}
func (m modInfo) renderDescriptionText(text string, converter *md.Converter) string {
text = strings.TrimSpace(text)
if text == "" {
text = "(No notes provided)"
}
markdownDescription, err := converter.ConvertString(text)
if err != nil {
slog.Error("failed to convert html to markdown", slog.Any("err", err))
markdownDescription = text
}
description, err := glamour.Render(markdownDescription, "dark")
if err != nil {
slog.Error("failed to render markdown", slog.Any("err", err))
description = text
}
return description
}
func (m modInfo) renderCompatInfo(state ficsit.CompatibilityState) string {
stateText := string(state)
switch state {
case ficsit.CompatibilityStateWorks:
return utils.CompatWorksStyle.Render(stateText)
case ficsit.CompatibilityStateDamaged:
return utils.CompatDamagedStyle.Render(stateText)
case ficsit.CompatibilityStateBroken:
return utils.CompatBrokenStyle.Render(stateText)
default:
return utils.CompatUntestedStyle.Render("Unknown")
}
}
func (m modInfo) View() string {
if m.error != nil {
helpBar := lipgloss.NewStyle().Padding(1, 2).Render(m.help.View(m.keys))

View file

@ -12,6 +12,13 @@ var (
NonListTitleStyle = TitleStyle.Copy().MarginLeft(2).Background(lipgloss.Color("#b34100"))
)
var (
CompatWorksStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#00b12d"))
CompatDamagedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#e69000"))
CompatBrokenStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#e60000"))
CompatUntestedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#838383"))
)
var (
LogoForegroundStyles = []lipgloss.Style{
lipgloss.NewStyle().Foreground(lipgloss.Color("#ff5f00")).Background(lipgloss.Color("#ff5f00")),

View file

@ -5,25 +5,80 @@ package main
import (
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
_ "github.com/Khan/genqlient/generate"
"github.com/spf13/cobra/doc"
"github.com/satisfactorymodding/ficsit-cli/cmd"
_ "github.com/Khan/genqlient/generate"
)
//go:generate go run github.com/Khan/genqlient
//go:generate go run -tags tools tools.go
func main() {
var err error
_ = os.RemoveAll("./docs/")
if err := os.Mkdir("./docs/", 0777); err != nil {
if err = os.Mkdir("./docs/", 0o777); err != nil {
panic(err)
}
err := doc.GenMarkdownTree(cmd.RootCmd, "./docs/")
err = doc.GenMarkdownTree(cmd.RootCmd, "./docs/")
if err != nil {
panic(err)
}
// replace user dir information with generic username
baseCacheDir, err := os.UserCacheDir()
if err != nil {
panic(err)
}
var baseLocalDir string
switch runtime.GOOS {
case "windows":
baseLocalDir = os.Getenv("APPDATA")
case "linux":
baseLocalDir = filepath.Join(os.Getenv("HOME"), ".local", "share")
default:
panic("unsupported platform: " + runtime.GOOS)
}
docFiles, err := os.ReadDir("./docs/")
if err != nil {
panic(err)
}
user, err := user.Current()
if err != nil {
panic(err)
}
for _, f := range docFiles {
fPath := "./docs/" + f.Name()
oldContents, err := os.ReadFile(fPath)
if err != nil {
panic(err)
}
newContents := strings.ReplaceAll(
string(oldContents),
baseCacheDir,
strings.ReplaceAll(baseCacheDir, user.Username, "{{Username}}"),
)
newContents = strings.ReplaceAll(
newContents,
baseLocalDir,
strings.ReplaceAll(baseLocalDir, user.Username, "{{Username}}"),
)
os.WriteFile(fPath, []byte(newContents), 0o777)
}
}