Merge pull request #6 from vlinkz/0.1.0alpha

Refactor around nix-data crate
This commit is contained in:
Victor Fuentes 2022-10-27 19:27:23 -04:00 committed by GitHub
commit 0ff92e7cc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 4492 additions and 1906 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
.envrc
/.direnv
/.vscode
/build
/result
/src/config.rs
/target
/src/resources.gresource

1209
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,27 @@
[package]
name = "nix-software-center"
version = "0.0.3"
version = "0.1.0"
edition = "2021"
default-run = "nix-software-center"
[dependencies]
relm4 = { git = "https://github.com/Relm4/Relm4", tag = "v0.5.0-beta.2", features = ["all"] }
relm4-components = { package = "relm4-components", git = "https://github.com/Relm4/Relm4", tag = "v0.5.0-beta.2"}
adw = { package = "libadwaita", git = "https://gitlab.gnome.org/World/Rust/libadwaita-rs", features = ["v1_2", "gtk_v4_6"] }
gtk = { package = "gtk4", git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_6"] }
relm4 = { version = "0.5.0-beta.4", features = ["all"] }
relm4-components = { package = "relm4-components", version = "0.5.0-beta.4"}
adw = { package = "libadwaita", version = "0.2", features = ["v1_2", "gtk_v4_6"] }
gtk = { package = "gtk4", version = "0.5", features = ["v4_6"] }
tokio = { version = "1.21", features = ["rt", "macros", "time", "rt-multi-thread", "sync", "process"] }
tracker = "0.1"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
simd-json = { version = "0.6", features = ["allow-non-simd"] }
nix-editor = "0.2.12"
nix-editor = "0.3.0-beta.1"
nix-data = { git = "https://github.com/snowflakelinux/nix-data", rev = "a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95" }
sqlx = { version = "0.6", features = [ "runtime-tokio-native-tls" , "sqlite" ] }
html2pango = "0.5"
brotli = "3.3"
log = "0.4"
pretty_env_logger = "0.4"
flate2 = "1.0"
@ -30,11 +31,8 @@ reqwest = { version = "0.11", features = ["blocking"] }
sha256 = "1.0"
image = "0.24"
spdx = "0.9"
edit-distance = "2.1"
ijson = "0.1"
strum = "0.24"
strum_macros = "0.24"
which = "4.3"
anyhow = "1.0"
[workspace]
members = [".", "nsc-helper"]

528
data/icons/nsc-audio.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="12" x2="116" y1="64" y2="64">
<stop offset="0" stop-color="#77767b"/>
<stop offset="0.05" stop-color="#c0bfbc"/>
<stop offset="0.1" stop-color="#9a9996"/>
<stop offset="0.899999" stop-color="#9a9996"/>
<stop offset="0.95" stop-color="#c0bfbc"/>
<stop offset="1" stop-color="#77767b"/>
</linearGradient>
<filter id="b" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="c">
<g filter="url(#b)">
<rect fill-opacity="0.05" height="128" width="128"/>
</g>
</mask>
<radialGradient id="d" cx="63.999996" cy="194.190475" gradientTransform="matrix(4.727273 -0.00000079 0.0000003 1.636364 -230.545471 -205.766182)" gradientUnits="userSpaceOnUse" r="44">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="1" stop-color="#ffffff" stop-opacity="0.094118"/>
</radialGradient>
<clipPath id="e">
<rect height="152" width="192"/>
</clipPath>
<path d="m 20 22 h 88 c 4.417969 0 8 3.582031 8 8 v 78 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -78 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 20 12 h 88 c 4.417969 0 8 3.582031 8 8 v 80 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -80 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
<path d="m 20 104 h 88 c 2.210938 0 4 -1.789062 4 -4 v -80 c 0 -2.210938 -1.789062 -4 -4 -4 h -88 c -2.210938 0 -4 1.789062 -4 4 v 80 c 0 2.210938 1.789062 4 4 4 z m 0 0" fill="#241f31"/>
<g clip-path="url(#e)" mask="url(#c)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 116 116 h -88 v -78 h 88 z m 0 0" fill="url(#d)"/>
</g>
<path d="m 24 28 h 28 v 4 h -28 z m 0 0" fill="#ff7800"/>
<path d="m 24 36 h 16 v 4 h -16 z m 0 0" fill="#deddda"/>
<path d="m 32 44 h 42 v 4 h -42 z m 0 0" fill="#3584e4"/>
<path d="m 32 52 h 22 v 4 h -22 z m 0 0" fill="#deddda"/>
<path d="m 40 60 h 36 v 4 h -36 z m 0 0" fill="#deddda"/>
<path d="m 40 68 h 20 v 4 h -20 z m 0 0" fill="#8ff0a4"/>
<path d="m 48 76 h 24 v 4 h -24 z m 0 0" fill="#ff7800"/>
<path d="m 24 84 h 32 v 4 h -32 z m 0 0" fill="#deddda"/>
<path d="m 24 92 h 18 v 4 h -18 z m 0 0" fill="#3584e4"/>
<path d="m 32 76 h 14 v 4 h -14 z m 0 0" fill="#8ff0a4"/>
<path d="m 62 68 h 20 v 4 h -20 z m 0 0" fill="#deddda"/>
<path d="m 78 60 h 18 v 4 h -18 z m 0 0" fill="#3584e4"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

1135
data/icons/nsc-gaming.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientTransform="matrix(0.25 0 0 0.244048 -0.499619 50.195877)" gradientUnits="userSpaceOnUse" x1="48" x2="464" y1="44" y2="44">
<stop offset="0" stop-color="#babdb6"/>
<stop offset="0.0416667" stop-color="#f6f5f4"/>
<stop offset="0.0833333" stop-color="#d5d3cf"/>
<stop offset="0.916667" stop-color="#deddda"/>
<stop offset="0.958333" stop-color="#f6f5f4"/>
<stop offset="1" stop-color="#babdb6"/>
</linearGradient>
<linearGradient id="b" gradientTransform="matrix(-0.471598 0 0 0.471598 569.325439 -130.366928)" gradientUnits="userSpaceOnUse" x1="953.275024" x2="944.207458" y1="350.855988" y2="359.923553">
<stop offset="0" stop-color="#e9b96e"/>
<stop offset="1" stop-color="#dc9321"/>
</linearGradient>
<linearGradient id="c" gradientTransform="matrix(-0.358336 0 0 0.358336 230.872086 1.097)" gradientUnits="userSpaceOnUse" x1="418.838409" x2="433.349823" y1="227" y2="212.868271">
<stop offset="0" stop-color="#9a9996"/>
<stop offset="0.415508" stop-color="#c0bfbc"/>
<stop offset="1" stop-color="#deddda"/>
</linearGradient>
<radialGradient id="d" cx="450.948059" cy="225.394623" gradientTransform="matrix(-0.658592 0 0 0.658592 370.111938 -72.351868)" gradientUnits="userSpaceOnUse" r="39.999989">
<stop offset="0" stop-color="#5b5b5b"/>
<stop offset="0.634455" stop-color="#262e39"/>
<stop offset="1" stop-color="#113f78"/>
</radialGradient>
<filter id="e" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="f">
<g filter="url(#e)">
<rect fill-opacity="0.3" height="128" width="128"/>
</g>
</mask>
<clipPath id="g">
<rect height="152" width="192"/>
</clipPath>
<linearGradient id="h" gradientUnits="userSpaceOnUse" x1="19.25" x2="54.820038" y1="55.999985" y2="91.570023">
<stop offset="0" stop-color="#dc8add"/>
<stop offset="1" stop-color="#103c72"/>
</linearGradient>
<radialGradient id="i" cx="67.502945" cy="244.504639" gradientTransform="matrix(1.001091 -0.00000013 0.00000014 0.81247 -0.576645 -108.652573)" gradientUnits="userSpaceOnUse" r="11.077337">
<stop offset="0" stop-color="#113f78" stop-opacity="0"/>
<stop offset="0.786035" stop-color="#113f78" stop-opacity="0.105882"/>
<stop offset="1" stop-color="#103c72"/>
</radialGradient>
<mask id="j">
<g filter="url(#e)">
<rect fill-opacity="0.2" height="128" width="128"/>
</g>
</mask>
<clipPath id="k">
<rect height="152" width="192"/>
</clipPath>
<path d="m 24 123 v 1 h 16 v -1 z m 64 0 v 1 h 16 v -1 z m 0 0" fill="#9a9996"/>
<path d="m 88 124 v -4 l -24 -96 v 4 z" fill="#77767b" fill-rule="evenodd"/>
<path d="m 40 124 v -4 l 24 -96 v 4 z" fill="#77767b" fill-rule="evenodd"/>
<path d="m 64 4 c -2.90625 0.003906 -5.417969 2.027344 -6.039062 4.867188 l -0.003907 -0.003907 l -33.957031 114.136719 h 16 l 24 -101 l 24 101 h 16 l -33.992188 -114.285156 l -0.007812 0.011718 c -0.671875 -2.773437 -3.148438 -4.722656 -6 -4.726562 z m 0 5 c 1.65625 0 3 1.34375 3 3 s -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 z m 0 0" fill="#c0bfbc"/>
<path d="m 20 30 h 88 c 4.417969 0 8 3.582031 8 8 v 66 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -66 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
<path d="m 20 20 h 88 c 4.417969 0 8 3.582031 8 8 v 72 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -72 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#f6f5f4"/>
<path d="m 128 36 l -48.90625 48.910156 c -2.199219 2.285156 -5.84375 2.324219 -8.085938 0.082032 c -2.242187 -2.242188 -2.203124 -5.886719 0.082032 -8.085938 l 41.132812 -41.132812 c 4.898438 -4.203126 11.777344 -3.773438 15.777344 0.226562 z m 0 0" fill="url(#b)"/>
<path d="m 90.683594 59.585938 c 5.148437 0.003906 7.6875 6.257812 3.996094 9.847656 l -19.066407 21.058594 c -2.785156 2.828124 -7.339843 2.847656 -10.144531 0.039062 c -2.804688 -2.804688 -2.785156 -7.359375 0.042969 -10.140625 l 21.058593 -19.066406 c 1.078126 -1.113281 2.5625 -1.738281 4.113282 -1.738281 z m 0 0" fill="url(#c)"/>
<path d="m 72 68 c 8.835938 0 16 7.164062 16 16 s -7.164062 16 -16 16 h -16 v -16 c 0 -8.835938 7.164062 -16 16 -16 z m 0 0" fill="url(#d)"/>
<g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 72.003906 95 c 0 -1.65625 1.339844 -2.996094 2.996094 -2.996094 s 2.996094 1.339844 2.996094 2.996094 s -1.339844 2.996094 -2.996094 2.996094 s -2.996094 -1.339844 -2.996094 -2.996094 z m 0 0" fill="#ffffff"/>
</g>
<path d="m 12 39.867188 v 24 c 2.003906 -1.125 4.425781 -1.488282 6.671875 -1.003907 s 4.304687 1.8125 5.667969 3.664063 c 1.761718 2.390625 2.3125 5.460937 2.457031 8.429687 c 0.144531 2.964844 -0.066406 5.957031 0.394531 8.894531 c 0.628906 3.996094 2.539063 7.792969 5.410156 10.648438 c 2.867188 2.855469 6.6875 4.753906 10.703126 5.269531 c 2.609374 0.335938 5.253906 0.203125 7.886718 0.210938 l 4.808594 0.019531 c 0 -0.441406 0 -0.886719 0 -1.328125 c 0 -0.222656 0 -0.449219 0 -0.671875 c -2.035156 -0.476562 -4.085938 -0.863281 -6.15625 -1.160156 c -1.339844 -0.191406 -2.695312 -0.34375 -3.996094 -0.734375 c -1.300781 -0.386719 -2.5625 -1.023438 -3.460937 -2.039063 c -0.757813 -0.855468 -1.226563 -1.941406 -1.429688 -3.066406 c -0.207031 -1.121094 -0.152343 -2.28125 0.046875 -3.402344 c 0.40625 -2.246094 1.390625 -4.339844 2.132813 -6.5 c 2.398437 -6.988281 2.167969 -14.796875 -0.375 -21.730468 c -2.804688 -7.644532 -8.546875 -14.3125 -16.011719 -17.5625 c -4.605469 -2.007813 -9.78125 -2.6875 -14.75 -1.9375 z m 0 0" fill="url(#h)"/>
<path d="m 46.90625 96.375 l 4.285156 3.605469 l 18.808594 0.019531 l -2 -3 c -3.144531 -4.714844 -9.132812 -9 -12 -9 c 0 6 -5.5625 9.097656 -9.09375 8.375 z m 0 0" fill="url(#i)"/>
<g clip-path="url(#k)" mask="url(#j)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 35 128 l -0.621094 2 h 16.054688 l 0.523437 -1.972656 z m 57.988281 0 l 0.5 2 h 16.132813 l -0.621094 -2 z m 0 0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 536 B

After

Width:  |  Height:  |  Size: 536 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
<path d="m 7.863281 1 c -0.269531 0.003906 -0.535156 0.027344 -0.800781 0.0625 c -2.109375 0.285156 -4.023438 1.527344 -5.125 3.4375 c -0.277344 0.476562 -0.113281 1.089844 0.367188 1.363281 c 0.476562 0.277344 1.089843 0.113281 1.363281 -0.363281 c 1.054687 -1.824219 3.128906 -2.789062 5.199219 -2.425781 c 1.679687 0.296875 3.058593 1.414062 3.714843 2.925781 h -1.582031 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 h 4 c 0.550781 0 1 -0.449219 1 -1 v -4 c 0 -0.550781 -0.449219 -1 -1 -1 s -1 0.449219 -1 1 v 1.398438 c -1.023438 -1.703126 -2.75 -2.933594 -4.785156 -3.292969 c -0.453125 -0.078125 -0.90625 -0.113281 -1.351563 -0.105469 z m -6.863281 7 c -0.550781 0 -1 0.449219 -1 1 v 4 c 0 0.550781 0.449219 1 1 1 s 1 -0.449219 1 -1 v -1.394531 c 1.140625 1.894531 3.132812 3.167969 5.390625 3.367187 c 2.707031 0.238282 5.3125 -1.117187 6.671875 -3.472656 c 0.277344 -0.476562 0.113281 -1.089844 -0.367188 -1.363281 c -0.226562 -0.136719 -0.5 -0.171875 -0.757812 -0.101563 c -0.257812 0.066406 -0.476562 0.234375 -0.609375 0.464844 c -0.972656 1.683594 -2.824219 2.648438 -4.765625 2.480469 c -1.832031 -0.160157 -3.414062 -1.308594 -4.144531 -2.980469 h 1.582031 c 0.550781 0 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0" fill="#2e3436"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

86
data/icons/nsc-video.svg Normal file
View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
<defs>
<linearGradient id="linear0" gradientUnits="userSpaceOnUse" x1="-424.457947" y1="195.077911" x2="-340.457947" y2="263.827911" gradientTransform="matrix(0.380952,0,0,0.64,209.698227,-82.849869)">
<stop offset="0" style="stop-color:rgb(86.274511%,54.11765%,86.666667%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(38.431373%,62.7451%,91.764706%);stop-opacity:1;"/>
</linearGradient>
<clipPath id="clip1">
<path d="M 24 42 L 40 42 L 40 86 L 24 86 Z M 24 42 "/>
</clipPath>
<clipPath id="clip2">
<path d="M 24 42 L 40 42 C 40 42 40 42.929688 40 44.078125 L 40 83.921875 C 40 85.070312 40 86 40 86 L 24 86 C 24 86 24 85.070312 24 83.921875 L 24 44.078125 C 24 42.929688 24 42 24 42 Z M 24 42 "/>
</clipPath>
<linearGradient id="linear1" gradientUnits="userSpaceOnUse" x1="-424.457947" y1="195.077911" x2="-340.457947" y2="263.827911" gradientTransform="matrix(0.380952,0,0,0.64,169.698227,-82.849867)">
<stop offset="0" style="stop-color:rgb(86.274511%,54.11765%,86.666667%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(38.431373%,62.7451%,91.764706%);stop-opacity:1;"/>
</linearGradient>
<clipPath id="clip3">
<path d="M 88 42 L 104 42 L 104 86 L 88 86 Z M 88 42 "/>
</clipPath>
<clipPath id="clip4">
<path d="M 88 42 L 104 42 C 104 42 104 42.929688 104 44.078125 L 104 83.921875 C 104 85.070312 104 86 104 86 L 88 86 C 88 86 88 85.070312 88 83.921875 L 88 44.078125 C 88 42.929688 88 42 88 42 Z M 88 42 "/>
</clipPath>
<linearGradient id="linear2" gradientUnits="userSpaceOnUse" x1="-424.457947" y1="195.077911" x2="-340.457947" y2="263.827911" gradientTransform="matrix(0.380952,0,0,0.64,249.698227,-82.849867)">
<stop offset="0" style="stop-color:rgb(86.274511%,54.11765%,86.666667%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(38.431373%,62.7451%,91.764706%);stop-opacity:1;"/>
</linearGradient>
</defs>
<g id="surface12140">
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear0);" d="M 48 42 L 80 42 C 80 42 80 42.929688 80 44.078125 L 80 83.921875 C 80 85.070312 80 86 80 86 L 48 86 C 48 86 48 85.070312 48 83.921875 L 48 44.078125 C 48 42.929688 48 42 48 42 Z M 48 42 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 24 28 L 104 28 C 104 28 104 28.40625 104 28.90625 L 104 29.09375 C 104 29.59375 104 30 104 30 L 24 30 C 24 30 24 29.59375 24 29.09375 L 24 28.90625 C 24 28.40625 24 28 24 28 Z M 24 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 24 24 L 104 24 C 104 24 104 24.894531 104 26 C 104 27.105469 104 28 104 28 L 24 28 C 24 28 24 27.105469 24 26 C 24 24.894531 24 24 24 24 Z M 24 24 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 25 90 L 104 90 C 104 90 104 90.449219 104 91 C 104 91.550781 104 92 104 92 L 25 92 C 25 92 25 91.550781 25 91 C 25 90.449219 25 90 25 90 Z M 25 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 26 86 L 104 86 C 104 86 104 86.449219 104 87 L 104 89 C 104 89.550781 104 90 104 90 L 26 90 C 26 90 26 89.550781 26 89 L 26 87 C 26 86.449219 26 86 26 86 Z M 26 86 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 25 100 L 104 100 C 104 100 104 100.894531 104 102 C 104 103.105469 104 104 104 104 L 25 104 C 25 104 25 103.105469 25 102 C 25 100.894531 25 100 25 100 Z M 25 100 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 26 96 L 104 96 C 104 96 104 96.449219 104 97 L 104 99 C 104 99.550781 104 100 104 100 L 26 100 C 26 100 26 99.550781 26 99 L 26 97 C 26 96.449219 26 96 26 96 Z M 26 96 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 24 38 L 104 38 C 104 38 104 38.40625 104 38.90625 L 104 41.09375 C 104 41.59375 104 42 104 42 L 24 42 C 24 42 24 41.59375 24 41.09375 L 24 38.90625 C 24 38.40625 24 38 24 38 Z M 24 38 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 24 34 L 104 34 C 104 34 104 34.894531 104 36 C 104 37.105469 104 38 104 38 L 24 38 C 24 38 24 37.105469 24 36 C 24 34.894531 24 34 24 34 Z M 24 34 "/>
<g clip-path="url(#clip1)" clip-rule="nonzero">
<g clip-path="url(#clip2)" clip-rule="nonzero">
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear1);" d="M 8 42 L 40 42 C 40 42 40 42.929688 40 44.078125 L 40 83.921875 C 40 85.070312 40 86 40 86 L 8 86 C 8 86 8 85.070312 8 83.921875 L 8 44.078125 C 8 42.929688 8 42 8 42 Z M 8 42 "/>
</g>
</g>
<path style="fill:none;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(96.470588%,82.745099%,17.647059%);stroke-opacity:1;stroke-miterlimit:4;" d="M 44 188 L 28 188 L 28 284 L 44 284 " transform="matrix(1,0,0,1,0,-172)"/>
<g clip-path="url(#clip3)" clip-rule="nonzero">
<g clip-path="url(#clip4)" clip-rule="nonzero">
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear2);" d="M 88 42 L 120 42 C 120 42 120 42.929688 120 44.078125 L 120 83.921875 C 120 85.070312 120 86 120 86 L 88 86 C 88 86 88 85.070312 88 83.921875 L 88 44.078125 C 88 42.929688 88 42 88 42 Z M 88 42 "/>
</g>
</g>
<path style="fill:none;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(96.470588%,82.745099%,17.647059%);stroke-opacity:1;stroke-miterlimit:4;" d="M 84 188 L 100 188 L 100 284 L 84 284 " transform="matrix(1,0,0,1,0,-172)"/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 40 36 L 48 36 C 48 36 48 37.691406 48 39.78125 L 48 40.859375 C 48 42.949219 48 44.640625 48 44.640625 L 40 44.640625 C 40 44.640625 40 42.949219 40 40.859375 L 40 39.78125 C 40 37.691406 40 36 40 36 Z M 40 36 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 40 36 L 48 36 C 48 36 48 37.140625 48 38.550781 L 48 87.449219 C 48 88.859375 48 90 48 90 L 40 90 C 40 90 40 88.859375 40 87.449219 L 40 38.550781 C 40 37.140625 40 36 40 36 Z M 40 36 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 80 36 L 88 36 C 88 36 88 37.691406 88 39.78125 L 88 40.859375 C 88 42.949219 88 44.640625 88 44.640625 L 80 44.640625 C 80 44.640625 80 42.949219 80 40.859375 L 80 39.78125 C 80 37.691406 80 36 80 36 Z M 80 36 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 80 36 L 88 36 C 88 36 88 37.140625 88 38.550781 L 88 87.449219 C 88 88.859375 88 90 88 90 L 80 90 C 80 90 80 88.859375 80 87.449219 L 80 38.550781 C 80 37.140625 80 36 80 36 Z M 80 36 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 108 94 L 116 94 C 116 94 116 95.117188 116 96.496094 L 116 101.503906 C 116 102.882812 116 104 116 104 L 108 104 C 108 104 108 102.882812 108 101.503906 L 108 96.496094 C 108 95.117188 108 94 108 94 Z M 108 94 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 108 86 L 116 86 L 116 100 L 108 100 Z M 108 86 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,64.705884%,3.921569%);fill-opacity:1;" d="M 24 116 L 44 116 L 44 118 L 24 118 Z M 24 116 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,64.705884%,3.921569%);fill-opacity:1;" d="M 84 116 L 104 116 L 104 118 L 84 118 Z M 84 116 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 32 28 L 36 28 C 36 28 36 28.1875 36 28.421875 L 36 28.539062 C 36 28.773438 36 28.960938 36 28.960938 L 32 28.960938 C 32 28.960938 32 28.773438 32 28.539062 L 32 28.421875 C 32 28.1875 32 28 32 28 Z M 32 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 32 28 L 36 28 C 36 28 36 28.125 36 28.285156 L 36 33.714844 C 36 33.875 36 34 36 34 L 32 34 C 32 34 32 33.875 32 33.714844 L 32 28.285156 C 32 28.125 32 28 32 28 Z M 32 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 44 28 L 52 28 C 52 28 52 28.1875 52 28.421875 L 52 28.539062 C 52 28.773438 52 28.960938 52 28.960938 L 44 28.960938 C 44 28.960938 44 28.773438 44 28.539062 L 44 28.421875 C 44 28.1875 44 28 44 28 Z M 44 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 44 28 L 52 28 C 52 28 52 28.125 52 28.285156 L 52 33.714844 C 52 33.875 52 34 52 34 L 44 34 C 44 34 44 33.875 44 33.714844 L 44 28.285156 C 44 28.125 44 28 44 28 Z M 44 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 60 28 L 68 28 C 68 28 68 28.1875 68 28.421875 L 68 28.539062 C 68 28.773438 68 28.960938 68 28.960938 L 60 28.960938 C 60 28.960938 60 28.773438 60 28.539062 L 60 28.421875 C 60 28.1875 60 28 60 28 Z M 60 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 60 28 L 68 28 C 68 28 68 28.125 68 28.285156 L 68 33.714844 C 68 33.875 68 34 68 34 L 60 34 C 60 34 60 33.875 60 33.714844 L 60 28.285156 C 60 28.125 60 28 60 28 Z M 60 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 76 28 L 84 28 C 84 28 84 28.1875 84 28.421875 L 84 28.539062 C 84 28.773438 84 28.960938 84 28.960938 L 76 28.960938 C 76 28.960938 76 28.773438 76 28.539062 L 76 28.421875 C 76 28.1875 76 28 76 28 Z M 76 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 76 28 L 84 28 C 84 28 84 28.125 84 28.285156 L 84 33.714844 C 84 33.875 84 34 84 34 L 76 34 C 76 34 76 33.875 76 33.714844 L 76 28.285156 C 76 28.125 76 28 76 28 Z M 76 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 92 28 L 96 28 C 96 28 96 28.1875 96 28.421875 L 96 28.539062 C 96 28.773438 96 28.960938 96 28.960938 L 92 28.960938 C 92 28.960938 92 28.773438 92 28.539062 L 92 28.421875 C 92 28.1875 92 28 92 28 Z M 92 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 92 28 L 96 28 C 96 28 96 28.125 96 28.285156 L 96 33.714844 C 96 33.875 96 34 96 34 L 92 34 C 92 34 92 33.875 92 33.714844 L 92 28.285156 C 92 28.125 92 28 92 28 Z M 92 28 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 32 90 L 36 90 C 36 90 36 90.1875 36 90.421875 L 36 90.539062 C 36 90.773438 36 90.960938 36 90.960938 L 32 90.960938 C 32 90.960938 32 90.773438 32 90.539062 L 32 90.421875 C 32 90.1875 32 90 32 90 Z M 32 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 32 90 L 36 90 C 36 90 36 90.125 36 90.285156 L 36 95.714844 C 36 95.875 36 96 36 96 L 32 96 C 32 96 32 95.875 32 95.714844 L 32 90.285156 C 32 90.125 32 90 32 90 Z M 32 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 44 90 L 52 90 C 52 90 52 90.1875 52 90.421875 L 52 90.539062 C 52 90.773438 52 90.960938 52 90.960938 L 44 90.960938 C 44 90.960938 44 90.773438 44 90.539062 L 44 90.421875 C 44 90.1875 44 90 44 90 Z M 44 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 44 90 L 52 90 C 52 90 52 90.125 52 90.285156 L 52 95.714844 C 52 95.875 52 96 52 96 L 44 96 C 44 96 44 95.875 44 95.714844 L 44 90.285156 C 44 90.125 44 90 44 90 Z M 44 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 60 90 L 68 90 C 68 90 68 90.1875 68 90.421875 L 68 90.539062 C 68 90.773438 68 90.960938 68 90.960938 L 60 90.960938 C 60 90.960938 60 90.773438 60 90.539062 L 60 90.421875 C 60 90.1875 60 90 60 90 Z M 60 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 60 90 L 68 90 C 68 90 68 90.125 68 90.285156 L 68 95.714844 C 68 95.875 68 96 68 96 L 60 96 C 60 96 60 95.875 60 95.714844 L 60 90.285156 C 60 90.125 60 90 60 90 Z M 60 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 76 90 L 84 90 C 84 90 84 90.1875 84 90.421875 L 84 90.539062 C 84 90.773438 84 90.960938 84 90.960938 L 76 90.960938 C 76 90.960938 76 90.773438 76 90.539062 L 76 90.421875 C 76 90.1875 76 90 76 90 Z M 76 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 76 90 L 84 90 C 84 90 84 90.125 84 90.285156 L 84 95.714844 C 84 95.875 84 96 84 96 L 76 96 C 76 96 76 95.875 76 95.714844 L 76 90.285156 C 76 90.125 76 90 76 90 Z M 76 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 92 90 L 96 90 C 96 90 96 90.1875 96 90.421875 L 96 90.539062 C 96 90.773438 96 90.960938 96 90.960938 L 92 90.960938 C 92 90.960938 92 90.773438 92 90.539062 L 92 90.421875 C 92 90.1875 92 90 92 90 Z M 92 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 92 90 L 96 90 C 96 90 96 90.125 96 90.285156 L 96 95.714844 C 96 95.875 96 96 96 96 L 92 96 C 92 96 92 95.875 92 95.714844 L 92 90.285156 C 92 90.125 92 90 92 90 Z M 92 90 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 108 32 L 116 32 C 116 32 116 33.117188 116 34.496094 L 116 39.503906 C 116 40.882812 116 42 116 42 L 108 42 C 108 42 108 40.882812 108 39.503906 L 108 34.496094 C 108 33.117188 108 32 108 32 Z M 108 32 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 108 24 L 116 24 L 116 38 L 108 38 Z M 108 24 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 12 94 L 20 94 C 20 94 20 95.117188 20 96.496094 L 20 101.503906 C 20 102.882812 20 104 20 104 L 12 104 C 12 104 12 102.882812 12 101.503906 L 12 96.496094 C 12 95.117188 12 94 12 94 Z M 12 94 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 12 86 L 20 86 L 20 100 L 12 100 Z M 12 86 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(10.196079%,37.254903%,70.588237%);fill-opacity:1;" d="M 12 32 L 20 32 C 20 32 20 33.117188 20 34.496094 L 20 39.503906 C 20 40.882812 20 42 20 42 L 12 42 C 12 42 12 40.882812 12 39.503906 L 12 34.496094 C 12 33.117188 12 32 12 32 Z M 12 32 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20.784314%,51.764709%,89.411765%);fill-opacity:1;" d="M 12 24 L 20 24 L 20 38 L 12 38 Z M 12 24 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

64
data/icons/nsc-web.svg Normal file
View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="98" x2="108" y1="112" y2="112">
<stop offset="0" stop-color="#16529c"/>
<stop offset="1" stop-color="#236ac0"/>
</linearGradient>
<linearGradient id="b" gradientTransform="matrix(0 -1 1 0 -157 121)" gradientUnits="userSpaceOnUse" x1="0.999999" x2="0.999999" y1="215" y2="171">
<stop offset="0" stop-color="#2166bb"/>
<stop offset="1" stop-color="#89eda9"/>
</linearGradient>
<filter id="c" height="100%" width="100%" x="0%" y="0%">
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="d">
<g filter="url(#c)">
<rect fill-opacity="0.5" height="128" width="128"/>
</g>
</mask>
<clipPath id="e">
<rect height="152" width="192"/>
</clipPath>
<mask id="f">
<g filter="url(#c)">
<rect fill-opacity="0.5" height="128" width="128"/>
</g>
</mask>
<clipPath id="g">
<rect height="152" width="192"/>
</clipPath>
<mask id="h">
<g filter="url(#c)">
<rect fill-opacity="0.5" height="128" width="128"/>
</g>
</mask>
<clipPath id="i">
<rect height="152" width="192"/>
</clipPath>
<path d="m 64 5 c 33.136719 0 60 26.863281 60 60 s -26.863281 60 -60 60 s -60 -26.863281 -60 -60 s 26.863281 -60 60 -60 z m 0 0" fill="url(#a)"/>
<path d="m 64 5 c -33.136719 0 -60 26.863281 -60 60 s 26.863281 60 60 60 z m 0 0" fill="url(#b)"/>
<path d="m 124 63 c 0 33.136719 -26.863281 60 -60 60 s -60 -26.863281 -60 -60 s 26.863281 -60 60 -60 s 60 26.863281 60 60 z m 0 0" fill="#40a1c8"/>
<path d="m 28.003906 64 c 0.125 13.914062 2.882813 27.367188 7.835938 38.25 c -3.941406 2.015625 -7.28125 4.441406 -9.863282 7.160156 c -13.640624 -11.171875 -21.675781 -27.78125 -21.96875 -45.410156 z m 0 0" fill="#49bbb0"/>
<path d="m 64 96 v 27 c -4.5 0 -8.988281 -0.507812 -13.375 -1.511719 c -5.800781 -4.058593 -10.894531 -10.691406 -14.78125 -19.238281 c 7.902344 -4.039062 17.867188 -6.25 28.15625 -6.25 z m 0 0" fill="#378bde"/>
<path d="m 99.996094 64 c -0.125 13.914062 -2.882813 27.367188 -7.839844 38.25 c 3.945312 2.015625 7.28125 4.441406 9.863281 7.160156 c 13.640625 -11.171875 21.675781 -27.78125 21.972657 -45.410156 z m 0 0" fill="#266ec6"/>
<path d="m 64 64 v 59 c 4.5 0 8.988281 -0.507812 13.375 -1.511719 c 13.472656 -9.433593 22.390625 -32.097656 22.621094 -57.488281 z m 0 0" fill="#378bde"/>
<path d="m 64 96 v 27 c 4.5 0 8.988281 -0.507812 13.375 -1.511719 c 5.800781 -4.058593 10.894531 -10.691406 14.78125 -19.238281 c -7.902344 -4.039062 -17.867188 -6.25 -28.15625 -6.25 z m 0 0" fill="#266ec6"/>
<path d="m 92.160156 102.25 c -3.890625 8.546875 -8.984375 15.175781 -14.78125 19.238281 c 9.035156 -2.066406 17.472656 -6.203125 24.644532 -12.078125 c -2.582032 -2.71875 -5.921876 -5.144531 -9.863282 -7.160156 z m 0 0" fill="#1e62b5"/>
<path d="m 64 3 c -33.136719 0 -60 26.863281 -60 60 c 0 0.332031 0.003906 0.667969 0.007812 1 h 59.992188 z m 0 0" fill="#53d795"/>
<path d="m 50.625 4.507812 c -9.039062 2.070313 -17.476562 6.203126 -24.648438 12.078126 c 2.582032 2.722656 5.921876 5.144531 9.867188 7.164062 c 3.890625 -8.550781 8.984375 -15.179688 14.78125 -19.242188 z m 0 0" fill="#72e99a"/>
<path d="m 64 3 c -4.5 0 -8.984375 0.507812 -13.375 1.507812 c -13.664062 9.570313 -22.625 32.734376 -22.625 58.492188 c 0 0.332031 0 0.667969 0.003906 1 h 35.996094 z m 0 0" fill="#49bbb0"/>
<path d="m 64 3 c -4.5 0 -8.984375 0.507812 -13.375 1.507812 c -5.796875 4.0625 -10.890625 10.691407 -14.78125 19.242188 c 7.90625 4.039062 17.867188 6.25 28.15625 6.25 z m 0 0" fill="#53d795"/>
<path d="m 64 3 c 33.136719 0 60 26.863281 60 60 c 0 0.332031 -0.003906 0.667969 -0.007812 1 h -59.992188 z m 0 0" fill="#378bde"/>
<path d="m 77.375 4.507812 c 9.039062 2.070313 17.476562 6.203126 24.648438 12.078126 c -2.582032 2.722656 -5.921876 5.144531 -9.863282 7.160156 c -3.894531 -8.546875 -8.988281 -15.175782 -14.785156 -19.238282 z m 0 0" fill="#40a1c8"/>
<path d="m 64 3 c 4.5 0 8.988281 0.507812 13.375 1.507812 c 13.664062 9.570313 22.625 32.734376 22.625 58.492188 c 0 0.332031 0 0.667969 -0.003906 1 h -35.996094 z m 0 0" fill="#40a1c8"/>
<path d="m 64 3 c 4.5 0 8.988281 0.507812 13.375 1.507812 c 5.796875 4.0625 10.890625 10.691407 14.78125 19.238282 c -7.90625 4.042968 -17.867188 6.253906 -28.15625 6.253906 z m 0 0" fill="#49bbb0"/>
<g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 169.5 24 v 1 h 13 v -1 z m 0 0" fill="#2e3436"/>
</g>
<g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 169.5 21 v 1 h 13 v -1 z m 0 0" fill="#2e3436"/>
</g>
<g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -8 -16)">
<path d="m 169.5 27 v 1 h 13 v -1 z m 0 0" fill="#2e3436"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,4 +1,5 @@
subdir('icons')
subdir('resources')
# Desktop file
desktop_conf = configuration_data()
desktop_conf.set('icon', application_id)

View File

@ -0,0 +1,8 @@
resources = gnome.compile_resources(
'resources',
'resources.gresource.xml',
gresource_bundle: true,
source_dir: meson.current_build_dir(),
install: true,
install_dir: pkgdatadir,
)

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/dev/vlinkz/NixSoftwareCenter/icons/scalable/emblems">
<file preprocess="xml-stripblanks" alias="nsc-home-symbolic.svg">../icons/nsc-home-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-installed-symbolic.svg">../icons/nsc-installed-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-update-symbolic.svg">../icons/nsc-update-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-audio.svg">../icons/nsc-audio.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-development.svg">../icons/nsc-development.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-gaming.svg">../icons/nsc-gaming.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-graphics.svg">../icons/nsc-graphics.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-video.svg">../icons/nsc-video.svg</file>
<file preprocess="xml-stripblanks" alias="nsc-web.svg">../icons/nsc-web.svg</file>
</gresource>
</gresources>

View File

@ -2,16 +2,6 @@
, lib ? import <nixpkgs/lib>
}:
let
libadwaita-git = pkgs.libadwaita.overrideAttrs (oldAttrs: rec {
version = "1.2.0";
src = pkgs.fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "GNOME";
repo = "libadwaita";
rev = version;
hash = "sha256-3lH7Vi9M8k+GSrCpvruRpLrIpMoOakKbcJlaAc/FK+U=";
};
});
nixos-appstream-data = (import
(pkgs.fetchFromGitHub {
owner = "vlinkz";
@ -19,18 +9,18 @@ let
rev = "66b3399e6d81017c10265611a151d1109ff1af1b";
hash = "sha256-oiEZD4sMpb2djxReg99GUo0RHWAehxSyQBbiz8Z4DJk=";
})
{ stdenv = pkgs.stdenv; lib = pkgs.lib; pkgs = pkgs; });
{ set = "all"; stdenv = pkgs.stdenv; lib = pkgs.lib; pkgs = pkgs; });
in
pkgs.stdenv.mkDerivation rec {
pname = "nix-software-center";
version = "0.0.3";
version = "0.1.0";
src = [ ./. ];
cargoDeps = pkgs.rustPlatform.fetchCargoTarball {
inherit src;
name = "${pname}-${version}";
hash = "sha256-8eUFl3N1tVZ2j+S6iIIpFSH5F5fXAl5+Yz3xS/NxF2I=";
hash = "sha256-yZKhtc5Rnkk3QdASnIxHFAYKPbG0RWySXLBjhraFPuc=";
};
nativeBuildInputs = with pkgs; [
@ -54,7 +44,8 @@ pkgs.stdenv.mkDerivation rec {
glib
gtk4
gtksourceview5
libadwaita-git
libadwaita
libxml2
openssl
wayland
gnome.adwaita-icon-theme

View File

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1664195620,
"narHash": "sha256-/0V1a1gAR+QbiQe4aCxBoivhkxss0xyt2mBD6yDrgjw=",
"lastModified": 1666703756,
"narHash": "sha256-GwpMJ1hT+z1fMAUkaGtvbvofJQwdVFDEGVhfE82+AUk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "62228ccc672ed000f35b1e5c82e4183e46767e52",
"rev": "f994293d1eb8812f032e8919e10a594567cf6ef7",
"type": "github"
},
"original": {

View File

@ -10,16 +10,6 @@
pkgs = import nixpkgs {
inherit system;
};
libadwaita-git = pkgs.libadwaita.overrideAttrs (oldAttrs: rec {
version = "1.2.0";
src = pkgs.fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "GNOME";
repo = "libadwaita";
rev = version;
hash = "sha256-3lH7Vi9M8k+GSrCpvruRpLrIpMoOakKbcJlaAc/FK+U=";
};
});
nixos-appstream-data = pkgs.fetchFromGitHub {
owner = "vlinkz";
repo = "nixos-appstream-data";
@ -58,7 +48,8 @@
graphene
gtk4
gtksourceview5
libadwaita-git
libadwaita
libxml2
meson
ninja
openssl

View File

@ -1,7 +1,7 @@
project(
'nix-software-center',
'rust',
version: '0.0.3',
version: '0.1.0',
meson_version: '>= 0.59',
license: 'GPL-3.0-only',
)

View File

@ -27,6 +27,6 @@ cargo_build = custom_target(
cargo, 'build',
cargo_options,
'&&',
'cp', 'src' / rust_target / 'nsc-helper', '@OUTPUT@',
'cp', 'nsc-helper' / 'src' / rust_target / 'nsc-helper', '@OUTPUT@',
]
)

View File

@ -1,13 +1,21 @@
use adw::gio;
use nix_software_center::ui::window::AppModel;
use gtk::{prelude::ApplicationExt, glib};
use log::{error, info};
use nix_software_center::{ui::window::AppModel, config::RESOURCES_FILE};
use relm4::*;
use nix_software_center::config::PKGDATADIR;
fn main() {
gtk::init().unwrap();
pretty_env_logger::init();
if let Ok(res) = gio::Resource::load(PKGDATADIR.to_string() + "/resources.gresource") {
glib::set_application_name("Software Center");
if let Ok(res) = gio::Resource::load(RESOURCES_FILE) {
info!("Resource loaded: {}", RESOURCES_FILE);
gio::resources_register(&res);
} else {
error!("Failed to load resources");
}
let app = RelmApp::new(nix_software_center::config::APP_ID);
let application = app.app.clone();
app.run::<AppModel>(application);
gtk::Window::set_default_icon_name(nix_software_center::config::APP_ID);
let app = adw::Application::new(Some(nix_software_center::config::APP_ID), gio::ApplicationFlags::empty());
app.set_resource_base_path(Some("/dev/vlinkz/NixSoftwareCenter"));
let app = RelmApp::with_app(app);
app.run::<AppModel>(());
}

View File

@ -5,17 +5,6 @@ global_conf.set_quoted('PROFILE', profile)
global_conf.set_quoted('VERSION', version + version_suffix)
global_conf.set_quoted('GETTEXT_PACKAGE', gettext_package)
global_conf.set_quoted('LOCALEDIR', localedir)
gnome = import('gnome')
resources = gnome.compile_resources(
'resources',
'resources.gresource.xml',
gresource_bundle: true,
source_dir: meson.current_build_dir(),
install: true,
install_dir: pkgdatadir,
)
config = configure_file(
input: 'config.rs.in',
output: 'config.rs',
@ -51,6 +40,7 @@ cargo_build = custom_target(
console: true,
install: true,
install_dir: bindir,
depends: resources,
command: [
'env',
cargo_env,

View File

@ -1,56 +1,15 @@
use std::{
env,
error::Error,
fs::{self, File},
io::Write,
path::Path,
};
use anyhow::Result;
use nix_data::config::configfile::NixDataConfig;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
pub struct NscConfig {
pub systemconfig: Option<String>,
pub flake: Option<String>,
pub flakearg: Option<String>,
}
pub fn getconfig() -> Option<NscConfig> {
if let Ok(c) = getconfigval() {
pub fn getconfig() -> Option<NixDataConfig> {
if let Ok(c) = nix_data::config::configfile::getconfig() {
Some(c)
} else {
None
}
}
fn getconfigval() -> Result<NscConfig, Box<dyn Error>> {
let configfile = checkconfig()?;
let config: NscConfig =
serde_json::from_reader(File::open(format!("{}/config.json", configfile))?)?;
Ok(config)
}
fn checkconfig() -> Result<String, Box<dyn Error>> {
let cfgdir = format!("{}/.config/nix-software-center", env::var("HOME")?);
if !Path::is_file(Path::new(&format!("{}/config.json", &cfgdir))) {
if !Path::is_file(Path::new("/etc/nix-software-center/config.json")) {
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"No config file found",
)))
} else {
Ok("/etc/nix-software-center/".to_string())
}
} else {
Ok(cfgdir)
}
}
pub fn editconfig(config: NscConfig) -> Result<(), Box<dyn Error>> {
let cfgdir = format!("{}/.config/nix-software-center", env::var("HOME")?);
fs::create_dir_all(&cfgdir)?;
let json = serde_json::to_string_pretty(&config)?;
let mut file = File::create(format!("{}/config.json", cfgdir))?;
file.write_all(json.as_bytes())?;
pub fn editconfig(config: NixDataConfig) -> Result<()> {
nix_data::config::configfile::setuserconfig(config)?;
Ok(())
}
}

View File

@ -1,3 +1,3 @@
pub mod cache;
// pub mod cache;
pub mod packages;
pub mod config;

View File

@ -1,91 +1,58 @@
use flate2::bufread::GzDecoder;
use ijson::IString;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io::Read;
use std::{self, fs::File, collections::HashMap, error::Error, env, io::BufReader};
use std::{self, fs::File, collections::HashMap, io::{BufReader, Read}};
use log::*;
use anyhow::Result;
use crate::APPINFO;
#[derive(Serialize, Deserialize, Debug)]
pub struct PackageBase {
packages: HashMap<String, Package>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Package {
pub system: IString,
pub pname: IString,
pub meta: Meta,
pub version: IString,
#[serde(skip_deserializing)]
pub appdata: Option<AppData>,
}
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Meta {
pub broken: Option<bool>,
pub insecure: Option<bool>,
pub unsupported: Option<bool>,
pub unfree: Option<bool>,
pub description: Option<IString>,
#[serde(rename = "longDescription")]
pub longdescription: Option<IString>,
pub homepage: Option<StrOrVec>,
pub maintainers: Option<ijson::IValue>,
pub position: Option<IString>,
pub license: Option<LicenseEnum>,
pub platforms: Option<Platform>
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
#[serde(untagged)]
pub enum StrOrVec {
Single(IString),
List(Vec<IString>),
Single(String),
List(Vec<String>),
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
#[serde(untagged)]
pub enum Platform {
Single(IString),
List(Vec<IString>),
ListList(Vec<Vec<IString>>),
Single(String),
List(Vec<String>),
ListList(Vec<Vec<String>>),
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
#[serde(untagged)]
pub enum LicenseEnum {
Single(License),
List(Vec<License>),
SingleStr(IString),
VecStr(Vec<IString>),
SingleStr(String),
VecStr(Vec<String>),
Mixed(Vec<LicenseEnum>)
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
pub struct License {
pub free: Option<bool>,
#[serde(rename = "fullName")]
pub fullname: Option<IString>,
pub fullname: Option<String>,
#[serde(rename = "spdxId")]
pub spdxid: Option<IString>,
pub url: Option<IString>,
pub spdxid: Option<String>,
pub url: Option<String>,
}
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
pub struct PkgMaintainer {
pub email: Option<IString>,
pub github: Option<IString>,
pub matrix: Option<IString>,
pub name: Option<IString>
pub email: Option<String>,
pub github: Option<String>,
pub matrix: Option<String>,
pub name: Option<String>
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct AppData {
#[serde(rename = "Type")]
pub metatype: IString,
pub metatype: String,
#[serde(rename = "ID")]
pub id: String,
#[serde(rename = "Package")]
@ -110,7 +77,7 @@ pub struct AppData {
pub categories: Option<Vec<String>>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AppUrl {
pub homepage: Option<String>,
pub bugtracker: Option<String>,
@ -118,27 +85,27 @@ pub struct AppUrl {
pub donation: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AppIconList {
pub cached: Option<Vec<AppIcon>>,
pub stock: Option<String>,
// TODO: add support for other icon types
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct AppIcon {
pub name: String,
pub width: u32,
pub height: u32,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AppLaunchable {
#[serde(rename = "desktop-id")]
pub desktopid: Vec<String>
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AppProvides {
pub binaries: Option<Vec<String>>,
pub ids: Option<Vec<String>>,
@ -146,7 +113,7 @@ pub struct AppProvides {
pub libraries: Option<Vec<String>>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AppScreenshot {
pub default: Option<bool>,
pub thumbnails: Option<Vec<String>>,
@ -154,33 +121,12 @@ pub struct AppScreenshot {
pub sourceimage: Option<AppScreenshotImage>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct AppScreenshotImage {
pub url: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct FlakePkgs {
packages: HashMap<String, FlakeJson>
}
#[derive(Debug, Serialize, Deserialize)]
struct FlakeJson {
pname: IString,
version: IString,
}
pub async fn readpkgs() -> Result<HashMap<String, Package>, Box<dyn Error + Send + Sync>> {
info!("Reading package list");
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
let cachefile = format!("{}/packages.json", cachedir);
let file = File::open(cachefile)?;
let reader = BufReader::new(file);
trace!("Reading packages.json");
let pkgbase: PackageBase = simd_json::serde::from_reader(reader)?;
trace!("Finished reading packages.json");
let mut pkgs = pkgbase.packages;
debug!("APPDATADIR {}", APPINFO);
pub fn appsteamdata() -> Result<HashMap<String, AppData>> {
let appdata = File::open(&format!("{}/xmls/nixos_x86_64_linux.yml.gz", APPINFO))?;
let appreader = BufReader::new(appdata);
let mut d = GzDecoder::new(appreader);
@ -188,61 +134,15 @@ pub async fn readpkgs() -> Result<HashMap<String, Package>, Box<dyn Error + Sen
d.read_to_string(&mut s)?;
let mut files = s.split("\n---\n").collect::<Vec<_>>();
files.remove(0);
let mut out = HashMap::new();
for f in files {
if let Ok(appstream) = serde_yaml::from_str::<AppData>(f) {
if let Some(p) = pkgs.get_mut(&appstream.package.to_string()) {
p.appdata = Some(appstream);
}
out.insert(appstream.package.to_string(), appstream);
} else {
warn!("Failed to parse some appstream data");
}
}
Ok(pkgs)
Ok(out)
}
pub fn readlegacysyspkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
info!("Reading legacy system package list");
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
let cachefile = format!("{}/syspackages.json", cachedir);
if let Ok(f) = fs::read_to_string(&cachefile) {
if f.trim().is_empty() {
return Ok(HashMap::new());
}
}
let file = File::open(cachefile)?;
let reader = BufReader::new(file);
let newpkgs: HashMap<String, String> = simd_json::serde::from_reader(reader)?;
Ok(newpkgs)
}
pub fn readflakesyspkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
info!("Reading flake system package list");
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
let cachefile = format!("{}/syspackages.json", cachedir);
if let Ok(f) = fs::read_to_string(&cachefile) {
if f.trim().is_empty() {
return Ok(HashMap::new());
}
}
let file = File::open(cachefile)?;
let reader = BufReader::new(file);
let newpkgs: HashMap<String, FlakeJson> = simd_json::serde::from_reader(reader)?;
let newpkgs = newpkgs.into_iter().filter_map(|(k, v)| if let Some(pkg) = k.strip_prefix("legacyPackages.x86_64-linux.") { Some((pkg.to_string(), v.version.to_string())) } else { None }).collect::<HashMap<_, _>>();
Ok(newpkgs)
}
pub fn readprofilepkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
info!("Reading profile package list");
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
let cachefile = format!("{}/profilepackages.json", cachedir);
if let Ok(f) = fs::read_to_string(&cachefile) {
if f.trim().is_empty() {
return Ok(HashMap::new());
}
}
let file = File::open(cachefile)?;
let reader = BufReader::new(file);
let profilepkgs: FlakePkgs = simd_json::serde::from_reader(reader)?;
let profilepkgs = profilepkgs.packages.into_iter().map(|(pkg, v)| (pkg.to_string(), v.version.to_string())).collect::<HashMap<_, _>>();
Ok(profilepkgs)
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/dev/vlinkz/NixSoftwareCenter/">
<file preprocess="xml-stripblanks" alias="icons/scalable/emblems/compass-symbolic.svg">../data/icons/compass-symbolic.svg</file>
<file preprocess="xml-stripblanks" alias="icons/scalable/emblems/selection-mode-symbolic.svg">../data/icons/selection-mode-symbolic.svg</file>
</gresource>
</gresources>

View File

@ -17,7 +17,7 @@ pub enum AboutPageMsg {
#[relm4::component(pub)]
impl SimpleComponent for AboutPageModel {
type InitParams = gtk::Window;
type Init = gtk::Window;
type Input = AboutPageMsg;
type Output = AppMsg;
type Widgets = AboutPageWidgets;
@ -40,7 +40,7 @@ impl SimpleComponent for AboutPageModel {
}
fn init(
parent_window: Self::InitParams,
parent_window: Self::Init,
root: &Self::Root,
_sender: ComponentSender<Self>,
) -> ComponentParts<Self> {

View File

@ -1,22 +1,21 @@
use relm4::adw::prelude::*;
use relm4::gtk::pango;
use relm4::{factory::*, *};
use strum_macros::{EnumIter, Display};
use super::window::AppMsg;
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub struct PkgGroup {
pub category: PkgCategory,
}
#[derive(Debug, Display, Hash, EnumIter, Eq, PartialEq, Clone)]
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
pub enum PkgCategory {
Audio,
Development,
Games,
Graphics,
Network,
Web,
Video,
}
@ -33,7 +32,7 @@ impl FactoryComponent for PkgGroup {
type Output = PkgCategoryMsg;
type Widgets = PkgGroupWidgets;
type ParentWidget = gtk::FlowBox;
type ParentMsg = AppMsg;
type ParentInput = AppMsg;
view! {
gtk::FlowBoxChild {
@ -51,14 +50,14 @@ impl FactoryComponent for PkgGroup {
gtk::Image {
add_css_class: "icon-dropshadow",
set_icon_name: match self.category {
PkgCategory::Audio => Some("audio-x-generic"),
PkgCategory::Development => Some("computer"),
PkgCategory::Games => Some("input-gaming"),
PkgCategory::Graphics => Some("image-x-generic"),
PkgCategory::Network => Some("network-server"),
PkgCategory::Video => Some("video-x-generic"),
PkgCategory::Audio => Some("nsc-audio"),
PkgCategory::Development => Some("nsc-development"),
PkgCategory::Games => Some("nsc-gaming"),
PkgCategory::Graphics => Some("nsc-graphics"),
PkgCategory::Web => Some("nsc-web"),
PkgCategory::Video => Some("nsc-video"),
},
set_pixel_size: 32,
set_pixel_size: 40,
},
gtk::Label {
add_css_class: "title-2",
@ -69,7 +68,7 @@ impl FactoryComponent for PkgGroup {
PkgCategory::Development => "Development",
PkgCategory::Games => "Games",
PkgCategory::Graphics => "Graphics",
PkgCategory::Network => "Network",
PkgCategory::Web => "Web",
PkgCategory::Video => "Video",
},
set_ellipsize: pango::EllipsizeMode::End,
@ -95,7 +94,7 @@ impl FactoryComponent for PkgGroup {
}
}
fn output_to_parent_msg(output: Self::Output) -> Option<AppMsg> {
fn output_to_parent_input(output: Self::Output) -> Option<AppMsg> {
Some(match output {
PkgCategoryMsg::Open(x) => AppMsg::OpenCategoryPage(x),
})

View File

@ -1,6 +1,7 @@
use super::{window::*, categories::PkgCategory, categorytile::CategoryTile};
use adw::prelude::*;
use relm4::{factory::*, *};
use log::*;
#[tracker::track]
#[derive(Debug)]
@ -22,12 +23,19 @@ pub enum CategoryPageMsg {
UpdateInstalled(Vec<String>, Vec<String>)
}
#[derive(Debug)]
pub enum CategoryPageAsyncMsg {
PushRec(CategoryTile),
Push(CategoryTile),
}
#[relm4::component(pub)]
impl SimpleComponent for CategoryPageModel {
type InitParams = ();
impl Component for CategoryPageModel {
type Init = ();
type Input = CategoryPageMsg;
type Output = AppMsg;
type Widgets = CategoryPageWidgets;
type CommandOutput = CategoryPageAsyncMsg;
view! {
gtk::Box {
@ -45,7 +53,14 @@ impl SimpleComponent for CategoryPageModel {
#[wrap(Some)]
set_title_widget = &gtk::Label {
#[watch]
set_label: &model.category.to_string(),
set_label: match model.category {
PkgCategory::Audio => "Audio",
PkgCategory::Development => "Development",
PkgCategory::Games => "Games",
PkgCategory::Graphics => "Graphics",
PkgCategory::Web => "Web",
PkgCategory::Video => "Video",
},
},
},
gtk::ScrolledWindow {
@ -59,11 +74,14 @@ impl SimpleComponent for CategoryPageModel {
set_maximum_size: 1000,
set_tightening_threshold: 750,
if model.busy {
#[name(spinner)]
gtk::Spinner {
set_hexpand: true,
set_vexpand: true,
set_halign: gtk::Align::Center,
set_valign: gtk::Align::Center,
set_spinning: true,
set_height_request: 32,
set_size_request: (64, 64),
}
} else {
gtk::Box {
@ -115,14 +133,14 @@ impl SimpleComponent for CategoryPageModel {
}
fn init(
(): Self::InitParams,
(): Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = CategoryPageModel {
category: PkgCategory::Audio,
recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input),
apps: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input),
recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), sender.input_sender()),
apps: FactoryVecDeque::new(gtk::FlowBox::new(), sender.input_sender()),
busy: true,
tracker: 0
};
@ -139,30 +157,44 @@ impl SimpleComponent for CategoryPageModel {
self.reset();
match msg {
CategoryPageMsg::Close => {
let mut recapps_guard = self.recommendedapps.guard();
let mut apps_guard = self.apps.guard();
recapps_guard.clear();
apps_guard.clear();
sender.output(AppMsg::FrontFrontPage)
}
CategoryPageMsg::OpenPkg(pkg) => {
sender.output(AppMsg::OpenPkg(pkg))
}
CategoryPageMsg::Open(category, catrec, catall) => {
info!("CategoryPageMsg::Open");
self.set_category(category);
let mut recapps_guard = self.recommendedapps.guard();
recapps_guard.clear();
for app in catrec {
recapps_guard.push_back(app);
}
recapps_guard.drop();
let mut apps_guard = self.apps.guard();
apps_guard.clear();
for app in catall {
apps_guard.push_back(app);
}
apps_guard.drop();
sender.command(|out, shutdown| {
shutdown.register(async move {
for app in catrec {
out.send(CategoryPageAsyncMsg::PushRec(app));
tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
}
}).drop_on_shutdown()
});
sender.command(|out, shutdown| {
shutdown.register(async move {
for app in catall {
out.send(CategoryPageAsyncMsg::Push(app));
tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
}
}).drop_on_shutdown()
});
self.busy = false;
info!("DONE CategoryPageMsg::Open");
}
CategoryPageMsg::Loading(category) => {
info!("CategoryPageMsg::Loading");
self.set_category(category);
self.busy = true;
}
@ -199,4 +231,19 @@ impl SimpleComponent for CategoryPageModel {
}
}
fn update_cmd(&mut self, msg: Self::CommandOutput, _sender: ComponentSender<Self>) {
match msg {
CategoryPageAsyncMsg::PushRec(tile) => {
let mut recapps_guard = self.recommendedapps.guard();
recapps_guard.push_back(tile);
recapps_guard.drop();
}
CategoryPageAsyncMsg::Push(tile) => {
let mut apps_guard = self.apps.guard();
apps_guard.push_back(tile);
apps_guard.drop();
}
}
}
}

View File

@ -7,7 +7,7 @@ use relm4::adw::prelude::*;
use relm4::gtk::pango;
use relm4::{factory::*, *};
#[derive(Default, Debug, PartialEq, Clone)]
#[derive(Default, Debug, PartialEq, Eq, Clone)]
pub struct CategoryTile {
pub name: String,
pub pkg: String,
@ -31,7 +31,7 @@ impl FactoryComponent for CategoryTile {
type Output = CategoryTileMsg;
type Widgets = CategoryTileWidgets;
type ParentWidget = gtk::FlowBox;
type ParentMsg = CategoryPageMsg;
type ParentInput = CategoryPageMsg;
view! {
gtk::FlowBoxChild {
@ -176,7 +176,7 @@ impl FactoryComponent for CategoryTile {
}
}
fn output_to_parent_msg(output: Self::Output) -> Option<CategoryPageMsg> {
fn output_to_parent_input(output: Self::Output) -> Option<CategoryPageMsg> {
Some(match output {
CategoryTileMsg::Open(x) => CategoryPageMsg::OpenPkg(x),
})

View File

@ -28,7 +28,7 @@ pub enum InstalledPageMsg {
#[relm4::component(pub)]
impl SimpleComponent for InstalledPageModel {
type InitParams = (SystemPkgs, UserPkgs);
type Init = (SystemPkgs, UserPkgs);
type Input = InstalledPageMsg;
type Output = AppMsg;
type Widgets = InstalledPageWidgets;
@ -93,13 +93,13 @@ impl SimpleComponent for InstalledPageModel {
}
fn init(
(systempkgtype, userpkgtype): Self::InitParams,
(systempkgtype, userpkgtype): Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = InstalledPageModel {
installeduserlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input),
installedsystemlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input),
installeduserlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
installedsystemlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
updatetracker: 0,
userpkgtype,
systempkgtype,
@ -196,7 +196,7 @@ impl SimpleComponent for InstalledPageModel {
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct InstalledItem {
pub name: String,
pub pkg: Option<String>,
@ -207,7 +207,7 @@ pub struct InstalledItem {
pub busy: bool,
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub struct InstalledItemModel {
pub item: InstalledItem,
}
@ -230,7 +230,7 @@ impl FactoryComponent for InstalledItemModel {
type Output = InstalledItemMsg;
type Widgets = InstalledItemWidgets;
type ParentWidget = adw::gtk::ListBox;
type ParentMsg = InstalledPageMsg;
type ParentInput = InstalledPageMsg;
view! {
adw::PreferencesRow {
@ -363,7 +363,7 @@ impl FactoryComponent for InstalledItemModel {
}
}
fn output_to_parent_msg(output: Self::Output) -> Option<InstalledPageMsg> {
fn output_to_parent_input(output: Self::Output) -> Option<InstalledPageMsg> {
Some(match output {
InstalledItemMsg::Delete(item) => InstalledPageMsg::Remove(item),
})

View File

@ -1,8 +1,7 @@
use crate::parse::config::NscConfig;
use super::pkgpage::{InstallType, PkgAction, PkgMsg, WorkPkg};
use super::window::{SystemPkgs, UserPkgs};
use log::*;
use nix_data::config::configfile::NixDataConfig;
use relm4::*;
use std::error::Error;
use std::path::Path;
@ -25,7 +24,7 @@ pub struct InstallAsyncHandler {
#[derive(Debug)]
pub enum InstallAsyncHandlerMsg {
SetConfig(NscConfig),
SetConfig(NixDataConfig),
SetPkgTypes(SystemPkgs, UserPkgs),
Process(WorkPkg),
CancelProcess,
@ -39,11 +38,11 @@ pub struct InstallAsyncHandlerInit {
}
impl Worker for InstallAsyncHandler {
type InitParams = InstallAsyncHandlerInit;
type Init = InstallAsyncHandlerInit;
type Input = InstallAsyncHandlerMsg;
type Output = PkgMsg;
fn init(params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
fn init(params: Self::Init, _sender: relm4::ComponentSender<Self>) -> Self {
Self {
process: None,
work: None,

View File

@ -2,6 +2,7 @@ use adw::gio;
use adw::prelude::*;
use html2pango;
use image::{imageops::FilterType, ImageFormat};
use nix_data::config::configfile::NixDataConfig;
use relm4::actions::RelmAction;
use relm4::actions::RelmActionGroup;
use relm4::gtk::pango;
@ -22,9 +23,7 @@ use std::{
};
use log::*;
use crate::parse::config::NscConfig;
use crate::parse::packages::PkgMaintainer;
use crate::parse::packages::StrOrVec;
use crate::ui::installworker::InstallAsyncHandlerMsg;
use super::installworker::InstallAsyncHandler;
@ -36,7 +35,7 @@ use super::{screenshotfactory::ScreenshotItem, window::AppMsg};
#[tracker::track]
#[derive(Debug)]
pub struct PkgModel {
config: NscConfig,
config: NixDataConfig,
name: String,
pkg: String,
pname: String,
@ -63,6 +62,7 @@ pub struct PkgModel {
installedsystempkgs: HashSet<String>,
workqueue: HashSet<WorkPkg>,
visible: bool,
}
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
@ -87,13 +87,13 @@ pub enum PkgAction {
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub enum Launch {
GtkApp(String),
TerminalApp(String),
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub enum CarouselPage {
First,
Middle,
@ -107,7 +107,7 @@ pub enum InstallType {
System,
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub struct License {
pub free: Option<bool>,
pub fullname: String,
@ -126,7 +126,7 @@ pub struct PkgInitModel {
pub description: Option<String>,
pub icon: Option<String>,
pub screenshots: Vec<String>,
pub homepage: Option<StrOrVec>,
pub homepage: Option<String>,
pub licenses: Vec<License>,
pub platforms: Vec<String>,
pub maintainers: Vec<PkgMaintainer>,
@ -135,7 +135,7 @@ pub struct PkgInitModel {
#[derive(Debug)]
pub enum PkgMsg {
UpdateConfig(NscConfig),
UpdateConfig(NixDataConfig),
UpdatePkgTypes(SystemPkgs, UserPkgs),
Open(Box<PkgInitModel>),
LoadScreenshot(String, usize, String),
@ -168,7 +168,7 @@ pub enum PkgAsyncMsg {
pub struct PkgPageInit {
pub syspkgs: SystemPkgs,
pub userpkgs: UserPkgs,
pub config: NscConfig,
pub config: NixDataConfig,
}
#[relm4::component(pub)]
@ -231,6 +231,8 @@ impl Component for PkgModel {
set_hexpand: true,
set_hscrollbar_policy: gtk::PolicyType::Never,
set_vscrollbar_policy: gtk::PolicyType::Automatic,
#[track(model.changed(PkgModel::visible()) && !self.visible)]
set_vadjustment: gtk::Adjustment::NONE,
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
adw::Clamp {
@ -617,7 +619,6 @@ impl Component for PkgModel {
set_homogeneous: true,
set_row_spacing: 5,
set_column_spacing: 4,
// set_margin_all: 15,
set_selection_mode: gtk::SelectionMode::None,
set_max_children_per_line: 2,
append = &gtk::FlowBoxChild {
@ -960,13 +961,11 @@ impl Component for PkgModel {
maintainers: vec![],
installeduserpkgs: HashSet::new(),
installedsystempkgs: HashSet::new(),
// installinguserpkgs: HashSet::new(),
// installingsystempkgs: HashSet::new(),
// removinguserpkgs: HashSet::new(),
syspkgtype: initparams.syspkgs,
userpkgtype: initparams.userpkgs,
workqueue: HashSet::new(),
launchable: None,
visible: false,
tracker: 0,
};
@ -1003,9 +1002,9 @@ impl Component for PkgModel {
})
};
group.add_action(nixenv);
group.add_action(nixprofile);
group.add_action(nixsystem);
group.add_action(&nixenv);
group.add_action(&nixprofile);
group.add_action(&nixsystem);
let actions = group.into_action_group();
widgets
@ -1027,8 +1026,8 @@ impl Component for PkgModel {
})
};
rungroup.add_action(launchaction);
rungroup.add_action(termaction);
rungroup.add_action(&launchaction);
rungroup.add_action(&termaction);
let runactions = rungroup.into_action_group();
widgets
@ -1051,6 +1050,7 @@ impl Component for PkgModel {
self.installworker.emit(InstallAsyncHandlerMsg::SetPkgTypes(syspkgs, userpkgs));
}
PkgMsg::Open(pkgmodel) => {
self.set_visible(true);
self.set_pkg(pkgmodel.pkg);
self.set_name(pkgmodel.name);
self.set_icon(pkgmodel.icon);
@ -1123,22 +1123,7 @@ impl Component for PkgModel {
self.description = Some(pango.strip_prefix('\n').unwrap_or(&pango).to_string());
}
if let Some(h) = pkgmodel.homepage {
match h {
StrOrVec::Single(h) => {
self.homepage = Some(h.to_string());
}
StrOrVec::List(h) => {
if let Some(first) = h.get(0) {
self.homepage = Some(first.to_string());
} else {
self.homepage = None;
}
}
}
} else {
self.homepage = None;
}
self.homepage = pkgmodel.homepage;
if pkgmodel.screenshots.len() <= 1 {
self.carpage = CarouselPage::Single;
@ -1150,14 +1135,14 @@ impl Component for PkgModel {
let mut scrn_guard = self.screenshots.guard();
scrn_guard.clear();
for _i in 0..pkgmodel.screenshots.len() {
scrn_guard.push_back(())
scrn_guard.push_back(());
}
}
for (i, url) in pkgmodel.screenshots.into_iter().enumerate() {
if let Ok(home) = env::var("HOME") {
let cachedir = format!("{}/.cache/nix-software-center", home);
let sha = digest(&url);
let sha = digest(url.to_string());
let scrnpath = format!("{}/screenshots/{}", cachedir, sha);
let pkg = self.pkg.clone();
@ -1197,7 +1182,6 @@ impl Component for PkgModel {
let mut content = Cursor::new(b);
if std::io::copy(&mut content, &mut file).is_ok() {
fn openimg(scrnpath: &str) -> Result<(), Box<dyn Error>> {
// let mut reader = Reader::new(Cursor::new(imgdata.buffer())).with_guessed_format().expect("Cursor io never fails");
let img = if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::Png) {
x
} else if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::Jpeg) {
@ -1289,13 +1273,14 @@ impl Component for PkgModel {
}
}
PkgMsg::Close => {
self.pkg = String::default();
self.name = String::default();
self.summary = None;
self.description = None;
self.icon = None;
let mut scrn_guard = self.screenshots.guard();
scrn_guard.clear();
// self.pkg = String::default();
// self.name = String::default();
// self.summary = None;
// self.description = None;
// self.icon = None;
// let mut scrn_guard = self.screenshots.guard();
// scrn_guard.clear();
self.set_visible(false);
sender.output(AppMsg::FrontPage)
}
PkgMsg::InstallUser => {
@ -1390,11 +1375,10 @@ impl Component for PkgModel {
PkgAction::Remove => {
self.installedsystempkgs.remove(&work.pkg);
}
};
sender.output(AppMsg::UpdateUpdatePkgs);
}
}
}
sender.output(AppMsg::UpdatePkgs(None));
sender.output(AppMsg::UpdateInstalledPkgs);
if let Some(n) = &work.notify {
match n {
NotifyPage::Installed => {
@ -1556,29 +1540,7 @@ impl Component for PkgModel {
}
fn launchterm(cmd: &str) {
if which::which("kgx").is_ok() {
let _ = Command::new("kgx").arg("-e").arg(&cmd).spawn();
} else if which::which("gnome-terminal").is_ok() {
let _ = Command::new("gnome-terminal").arg("--").arg(&cmd).spawn();
} else if which::which("konsole").is_ok() {
let _ = Command::new("konsole").arg("-e").arg(&cmd).spawn();
} else if which::which("mate-terminal").is_ok() {
let _ = Command::new("mate-terminal").arg("-e").arg(&cmd).spawn();
} else if which::which("xfce4-terminal").is_ok() {
let _ = Command::new("xfce4-terminal").arg("-e").arg(&cmd).spawn();
} else if which::which("tilix").is_ok() {
let _ = Command::new("tilix").arg("-e").arg(&cmd).spawn();
} else if which::which("terminology").is_ok() {
let _ = Command::new("terminology").arg("-e").arg(&cmd).spawn();
} else if which::which("alacritty").is_ok() {
let _ = Command::new("alacritty").arg("-e").arg(&cmd).spawn();
} else if which::which("urxvt").is_ok() {
let _ = Command::new("urxvt").arg("-e").arg(&cmd).spawn();
} else if which::which("xterm").is_ok() {
let _ = Command::new("xterm").arg("-e").arg(&cmd).spawn();
} else {
error!("No terminal detected!")
}
let _ = Command::new("kgx").arg("-e").arg(&cmd).spawn();
}
relm4::new_action_group!(ModeActionGroup, "mode");

View File

@ -8,7 +8,7 @@ use crate::APPINFO;
use super::window::AppMsg;
#[derive(Default, Debug, PartialEq)]
#[derive(Default, Debug, PartialEq, Eq)]
pub struct PkgTile {
pub name: String,
pub pkg: String,
@ -32,7 +32,7 @@ impl FactoryComponent for PkgTile {
type Output = PkgTileMsg;
type Widgets = PkgTileWidgets;
type ParentWidget = gtk::FlowBox;
type ParentMsg = AppMsg;
type ParentInput = AppMsg;
view! {
gtk::FlowBoxChild {
@ -171,7 +171,7 @@ impl FactoryComponent for PkgTile {
}
}
fn output_to_parent_msg(output: Self::Output) -> Option<AppMsg> {
fn output_to_parent_input(output: Self::Output) -> Option<AppMsg> {
Some(match output {
PkgTileMsg::Open(x) => AppMsg::OpenPkg(x),
})

View File

@ -1,9 +1,7 @@
use std::path::PathBuf;
use crate::parse::config::NscConfig;
use super::window::AppMsg;
use adw::prelude::*;
use nix_data::config::configfile::NixDataConfig;
use relm4::*;
use relm4_components::open_dialog::*;
@ -22,7 +20,7 @@ pub struct PreferencesPageModel {
#[derive(Debug)]
pub enum PreferencesPageMsg {
Show(NscConfig),
Show(NixDataConfig),
Open,
OpenFlake,
SetConfigPath(Option<PathBuf>),
@ -34,7 +32,7 @@ pub enum PreferencesPageMsg {
#[relm4::component(pub)]
impl SimpleComponent for PreferencesPageModel {
type InitParams = gtk::Window;
type Init = gtk::Window;
type Input = PreferencesPageMsg;
type Output = AppMsg;
type Widgets = PreferencesPageWidgets;
@ -165,7 +163,7 @@ impl SimpleComponent for PreferencesPageModel {
} @flakeentry,
#[track(model.changed(PreferencesPageModel::flake()))]
#[block_signal(flakeentry)]
set_text: &model.flakearg.as_ref().unwrap_or(&String::new())
set_text: model.flakearg.as_ref().unwrap_or(&String::new())
}
}
@ -174,21 +172,21 @@ impl SimpleComponent for PreferencesPageModel {
}
fn init(
parent_window: Self::InitParams,
parent_window: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let open_dialog = OpenDialog::builder()
.transient_for_native(root)
.launch(OpenDialogSettings::default())
.forward(&sender.input, |response| match response {
.forward(sender.input_sender(), |response| match response {
OpenDialogResponse::Accept(path) => PreferencesPageMsg::SetConfigPath(Some(path)),
OpenDialogResponse::Cancel => PreferencesPageMsg::Ignore,
});
let flake_file_dialog = OpenDialog::builder()
.transient_for_native(root)
.launch(OpenDialogSettings::default())
.forward(&sender.input, |response| match response {
.forward(sender.input_sender(), |response| match response {
OpenDialogResponse::Accept(path) => PreferencesPageMsg::SetFlakePath(Some(path)),
OpenDialogResponse::Cancel => PreferencesPageMsg::Ignore,
});
@ -211,9 +209,9 @@ impl SimpleComponent for PreferencesPageModel {
self.reset();
match msg {
PreferencesPageMsg::Show(config) => {
self.configpath = config.systemconfig.as_ref().map(|x| PathBuf::from(x));
self.set_flake(config.flake.as_ref().map(|x| PathBuf::from(x)));
self.set_flakearg(config.flakearg.clone());
self.configpath = config.systemconfig.as_ref().map(PathBuf::from);
self.set_flake(config.flake.as_ref().map(PathBuf::from));
self.set_flakearg(config.flakearg);
self.hidden = false;
}
PreferencesPageMsg::Open => self.open_dialog.emit(OpenDialogMsg::Open),

View File

@ -3,7 +3,7 @@ use relm4::{factory::*, *};
use super::pkgpage::PkgMsg;
#[derive(Default, Debug, PartialEq)]
#[derive(Default, Debug, PartialEq, Eq)]
pub struct ScreenshotItem {
pub path: Option<String>,
pub error: bool,
@ -20,7 +20,7 @@ impl FactoryComponent for ScreenshotItem {
type Output = ScreenshotItemMsg;
type Widgets = PkgTileWidgets;
type ParentWidget = adw::Carousel;
type ParentMsg = PkgMsg;
type ParentInput = PkgMsg;
view! {
gtk::Box {

View File

@ -16,16 +16,14 @@ pub struct SearchPageModel {
#[derive(Debug)]
pub enum SearchPageMsg {
Open,
Search(Vec<SearchItem>),
UpdateInstalled(HashSet<String>, HashSet<String>),
Close,
OpenRow(gtk::ListBoxRow)
}
#[relm4::component(pub)]
impl SimpleComponent for SearchPageModel {
type InitParams = ();
type Init = ();
type Input = SearchPageMsg;
type Output = AppMsg;
type Widgets = SearchPageWidgets;
@ -53,12 +51,12 @@ impl SimpleComponent for SearchPageModel {
}
fn init(
(): Self::InitParams,
(): Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = SearchPageModel {
searchitems: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input),
searchitems: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
searchitemtracker: 0,
tracker: 0,
};
@ -82,8 +80,6 @@ impl SimpleComponent for SearchPageModel {
searchitem_guard.drop();
self.update_searchitemtracker(|_| ());
}
SearchPageMsg::Open => {}
SearchPageMsg::Close => {}
SearchPageMsg::OpenRow(row) => {
let searchitem_guard = self.searchitems.guard();
for (i, child) in searchitem_guard.widget().iter_children().enumerate() {
@ -110,7 +106,7 @@ impl SimpleComponent for SearchPageModel {
}
}
#[derive(Default, Debug, PartialEq)]
#[derive(Default, Debug, PartialEq, Eq)]
pub struct SearchItem {
pub name: String,
pub pkg: String,
@ -122,7 +118,7 @@ pub struct SearchItem {
}
#[tracker::track]
#[derive(Default, Debug, PartialEq)]
#[derive(Default, Debug, PartialEq, Eq)]
pub struct SearchItemModel {
pub item: SearchItem,
}
@ -138,7 +134,7 @@ impl FactoryComponent for SearchItemModel {
type Output = SearchItemMsg;
type Widgets = SearchItemWidgets;
type ParentWidget = adw::gtk::ListBox;
type ParentMsg = SearchPageMsg;
type ParentInput = SearchPageMsg;
view! {
adw::PreferencesRow {

View File

@ -21,7 +21,7 @@ pub enum UpdateDialogMsg {
#[relm4::component(pub)]
impl SimpleComponent for UpdateDialogModel {
type InitParams = gtk::Window;
type Init = gtk::Window;
type Input = UpdateDialogMsg;
type Output = UpdatePageMsg;
type Widgets = UpdateDialogWidgets;
@ -99,7 +99,7 @@ impl SimpleComponent for UpdateDialogModel {
}
fn init(
parent_window: Self::InitParams,
parent_window: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {

View File

@ -1,7 +1,8 @@
use crate::{parse::{cache::channelver, config::NscConfig}, APPINFO};
use crate::APPINFO;
use super::{pkgpage::InstallType, window::*, updatedialog::{UpdateDialogModel, UpdateDialogMsg}, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg, UpdateAsyncHandlerInit}};
use adw::prelude::*;
use nix_data::config::configfile::NixDataConfig;
use relm4::{factory::*, gtk::pango, *};
use std::{path::Path, convert::identity};
use log::*;
@ -18,7 +19,7 @@ pub struct UpdatePageModel {
updatedialog: Controller<UpdateDialogModel>,
#[tracker::no_eq]
updateworker: WorkerController<UpdateAsyncHandler>,
config: NscConfig,
config: NixDataConfig,
systype: SystemPkgs,
usertype: UserPkgs,
updatetracker: u8,
@ -26,7 +27,7 @@ pub struct UpdatePageModel {
#[derive(Debug)]
pub enum UpdatePageMsg {
UpdateConfig(NscConfig),
UpdateConfig(NixDataConfig),
UpdatePkgTypes(SystemPkgs, UserPkgs),
Update(Vec<UpdateItem>, Vec<UpdateItem>),
OpenRow(usize, InstallType),
@ -45,12 +46,12 @@ pub struct UpdatePageInit {
pub window: gtk::Window,
pub systype: SystemPkgs,
pub usertype: UserPkgs,
pub config: NscConfig,
pub config: NixDataConfig,
}
#[relm4::component(pub)]
impl SimpleComponent for UpdatePageModel {
type InitParams = UpdatePageInit;
type Init = UpdatePageInit;
type Input = UpdatePageMsg;
type Output = AppMsg;
type Widgets = UpdatePageWidgets;
@ -277,7 +278,7 @@ impl SimpleComponent for UpdatePageModel {
}
fn init(
initparams: Self::InitParams,
initparams: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
@ -292,8 +293,8 @@ impl SimpleComponent for UpdatePageModel {
updateworker.emit(UpdateAsyncHandlerMsg::UpdateConfig(config.clone()));
let model = UpdatePageModel {
updateuserlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input),
updatesystemlist: FactoryVecDeque::new(gtk::ListBox::new(), &sender.input),
updateuserlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
updatesystemlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
channelupdate: None,
updatetracker: 0,
updatedialog,
@ -320,15 +321,21 @@ impl SimpleComponent for UpdatePageModel {
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateConfig(self.config.clone()));
}
UpdatePageMsg::UpdatePkgTypes(systype, usertype) => {
self.systype = systype.clone();
self.usertype = usertype.clone();
self.systype = systype;
self.usertype = usertype;
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdatePkgTypes(self.systype.clone(), self.usertype.clone()));
}
UpdatePageMsg::Update(updateuserlist, updatesystemlist) => {
info!("UpdatePageMsg::Update");
debug!("UPDATEUSERLIST: {:?}", updateuserlist);
debug!("UPDATESYSTEMLIST: {:?}", updatesystemlist);
self.channelupdate = channelver().unwrap_or(None);
self.channelupdate = match nix_data::cache::channel::uptodate() {
Ok(x) => {
x
},
Err(_) => None,
};
debug!("CHANNELUPDATE: {:?}", self.channelupdate);
self.update_updatetracker(|_| ());
let mut updateuserlist_guard = self.updateuserlist.guard();
updateuserlist_guard.clear();
@ -384,7 +391,7 @@ impl SimpleComponent for UpdatePageModel {
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateAll);
}
UpdatePageMsg::DoneWorking => {
sender.output(AppMsg::ReloadUpdate);
sender.output(AppMsg::UpdateInstalledPkgs);
}
UpdatePageMsg::DoneLoading => {
self.updatedialog.emit(UpdateDialogMsg::Done);
@ -396,7 +403,7 @@ impl SimpleComponent for UpdatePageModel {
}
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub struct UpdateItem {
pub name: String,
pub pkg: Option<String>,
@ -408,7 +415,7 @@ pub struct UpdateItem {
pub verto: Option<String>,
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Eq)]
pub struct UpdateItemModel {
item: UpdateItem,
}
@ -424,7 +431,7 @@ impl FactoryComponent for UpdateItemModel {
type Output = UpdateItemMsg;
type Widgets = UpdateItemWidgets;
type ParentWidget = adw::gtk::ListBox;
type ParentMsg = UpdatePageMsg;
type ParentInput = UpdatePageMsg;
view! {
adw::PreferencesRow {

View File

@ -1,10 +1,9 @@
use nix_data::config::configfile::NixDataConfig;
use relm4::*;
use std::{error::Error, path::Path, process::Stdio};
use tokio::io::AsyncBufReadExt;
use log::*;
use crate::parse::config::NscConfig;
use super::{
updatepage::UpdatePageMsg,
window::{SystemPkgs, UserPkgs},
@ -23,7 +22,7 @@ pub struct UpdateAsyncHandler {
#[derive(Debug)]
pub enum UpdateAsyncHandlerMsg {
UpdateConfig(NscConfig),
UpdateConfig(NixDataConfig),
UpdatePkgTypes(SystemPkgs, UserPkgs),
UpdateChannels,
@ -47,11 +46,11 @@ pub struct UpdateAsyncHandlerInit {
}
impl Worker for UpdateAsyncHandler {
type InitParams = UpdateAsyncHandlerInit;
type Init = UpdateAsyncHandlerInit;
type Input = UpdateAsyncHandlerMsg;
type Output = UpdatePageMsg;
fn init(params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
fn init(params: Self::Init, _sender: relm4::ComponentSender<Self>) -> Self {
Self {
process: None,
systemconfig: None,

View File

@ -2,11 +2,10 @@ use std::path::{PathBuf, Path};
use adw::prelude::*;
use log::info;
use nix_data::config::configfile::NixDataConfig;
use relm4::*;
use relm4_components::open_dialog::*;
use crate::parse::config::NscConfig;
use super::window::AppMsg;
#[tracker::track]
@ -36,7 +35,7 @@ pub enum WelcomeMsg {
#[relm4::component(pub)]
impl SimpleComponent for WelcomeModel {
type InitParams = gtk::Window;
type Init = gtk::Window;
type Input = WelcomeMsg;
type Output = AppMsg;
type Widgets = WelcomeWidgets;
@ -176,7 +175,7 @@ impl SimpleComponent for WelcomeModel {
}
fn init(
parent_window: Self::InitParams,
parent_window: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
@ -184,7 +183,7 @@ impl SimpleComponent for WelcomeModel {
let conf_dialog = OpenDialog::builder()
.transient_for_native(root)
.launch(OpenDialogSettings::default())
.forward(&sender.input, |response| match response {
.forward(sender.input_sender(), |response| match response {
OpenDialogResponse::Accept(path) => WelcomeMsg::UpdateConfPath(path),
OpenDialogResponse::Cancel => WelcomeMsg::Ignore,
});
@ -193,7 +192,7 @@ impl SimpleComponent for WelcomeModel {
let flake_dialog = OpenDialog::builder()
.transient_for_native(root)
.launch(OpenDialogSettings::default())
.forward(&sender.input, |response| match response {
.forward(sender.input_sender(), |response| match response {
OpenDialogResponse::Accept(path) => WelcomeMsg::UpdateFlakePath(path),
OpenDialogResponse::Cancel => WelcomeMsg::Ignore,
});
@ -222,7 +221,7 @@ impl SimpleComponent for WelcomeModel {
self.hidden = false;
}
WelcomeMsg::Close => {
let config = NscConfig {
let config = NixDataConfig {
systemconfig: self.confpath.as_ref().map(|x| x.to_string_lossy().to_string()),
flake: self.flakepath.as_ref().map(|x| x.to_string_lossy().to_string()),
flakearg: None,

File diff suppressed because it is too large Load Diff

View File

@ -1,423 +1,381 @@
use super::window::AppMsg;
use super::window::SystemPkgs;
use crate::parse::cache::checkcache;
use crate::parse::config::NscConfig;
use crate::parse::packages::readflakesyspkgs;
use crate::parse::packages::readpkgs;
use crate::parse::packages::readlegacysyspkgs;
use crate::parse::packages::Package;
use crate::parse::packages::readprofilepkgs;
use crate::parse::packages::appsteamdata;
use crate::parse::packages::AppData;
use crate::ui::categories::PkgCategory;
use crate::ui::window::UserPkgs;
use log::*;
use nix_data::config::configfile::NixDataConfig;
use rand::prelude::SliceRandom;
use rand::thread_rng;
use relm4::adw::prelude::*;
use relm4::*;
use sqlx::SqlitePool;
use std::{collections::HashMap, env};
use strum::IntoEnumIterator;
use log::*;
pub struct WindowAsyncHandler;
#[derive(Debug)]
pub enum WindowAsyncHandlerMsg {
CheckCache(CacheReturn, SystemPkgs, UserPkgs, NscConfig),
}
#[derive(Debug, PartialEq)]
pub enum CacheReturn {
Init,
Update,
CheckCache(SystemPkgs, UserPkgs, NixDataConfig),
}
impl Worker for WindowAsyncHandler {
type InitParams = ();
type Init = ();
type Input = WindowAsyncHandlerMsg;
type Output = AppMsg;
fn init(_params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
fn init(_params: Self::Init, _sender: relm4::ComponentSender<Self>) -> Self {
Self
}
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
match msg {
WindowAsyncHandlerMsg::CheckCache(cr, syspkgs, userpkgs, config) => {
WindowAsyncHandlerMsg::CheckCache(syspkgs, userpkgs, _config) => {
info!("WindowAsyncHandlerMsg::CheckCache");
let syspkgs2 = syspkgs.clone();
let userpkgs2 = userpkgs.clone();
let config = config.clone();
relm4::spawn(async move {
match checkcache(syspkgs2, userpkgs2, config) {
Ok(_) => {}
Err(e) => {
warn!("FAILED TO CHECK CACHE");
warn!("{}", e);
sender.output(AppMsg::LoadError(
String::from("Could not load cache"),
String::from(
"Try connecting to the internet or launching the application again",
),
));
return;
}
}
let pkgs = match readpkgs().await {
Ok(pkgs) => pkgs,
Err(e) => {
warn!("FAILED TO LOAD PKGS");
warn!("{}", e);
sender.output(AppMsg::LoadError(
String::from("Could not load packages"),
String::from(
"Try connecting to the internet or launching the application again",
),
));
return;
}
};
let newpkgs = match syspkgs {
SystemPkgs::Legacy => {
match readlegacysyspkgs() {
Ok(newpkgs) => newpkgs,
Err(e) => {
warn!("FAILED TO LOAD NEW PKGS");
warn!("{}", e);
sender.output(AppMsg::LoadError(
String::from("Could not load new packages"),
String::from(
"Try connecting to the internet or launching the application again",
),
));
return;
}
}
}
SystemPkgs::Flake => {
match readflakesyspkgs() {
Ok(newpkgs) => newpkgs,
Err(e) => {
warn!("FAILED TO LOAD NEW PKGS");
warn!("{}", e);
sender.output(AppMsg::LoadError(
String::from("Could not load new packages"),
String::from(
"Try connecting to the internet or launching the application again",
),
));
return;
}
}
}
SystemPkgs::None => {
HashMap::new()
}
};
let profilepkgs = match userpkgs {
UserPkgs::Env => None,
UserPkgs::Profile => if let Ok(r) = readprofilepkgs() { Some(r) } else { None },
};
let mut recpicks = vec![];
let mut catpicks: HashMap<PkgCategory, Vec<String>> = HashMap::new();
let mut catpkgs: HashMap<PkgCategory, Vec<String>> = HashMap::new();
println!("Connecting to DB");
let pkgdb = nix_data::cache::nixos::nixospkgs().await.unwrap();
let pool = SqlitePool::connect(&format!("sqlite://{}", pkgdb))
.await
.unwrap();
if cr == CacheReturn::Init {
let desktopenv = env::var("XDG_CURRENT_DESKTOP").unwrap_or_default();
let appdatapkgs = pkgs
.iter()
.filter(|(x, _)| {
if let Some(p) = pkgs.get(*x) {
if let Some(data) = &p.appdata {
(if let Some(i) = &data.icon {
i.cached.is_some()
} else {
false
}) && data.description.is_some()
&& data.name.is_some()
&& data.launchable.is_some()
&& data.screenshots.is_some()
&& (!x.starts_with("gnome.") || desktopenv == "GNOME")
&& (!x.starts_with("xfce.") || desktopenv == "XFCE")
&& (!x.starts_with("mate.") || desktopenv == "MATE")
&& (!x.starts_with("cinnamon.")
|| desktopenv == "X-Cinnamon")
&& (!x.starts_with("libsForQt5") || desktopenv == "KDE")
&& (!x.starts_with("pantheon.")
|| desktopenv == "Pantheon")
} else {
false
}
} else {
false
}
})
.collect::<HashMap<_, _>>();
let mut recommendedpkgs = appdatapkgs
.keys()
.map(|x| x.to_string())
.collect::<Vec<_>>();
let mut rng = thread_rng();
recommendedpkgs.shuffle(&mut rng);
let mut desktoppicks = recommendedpkgs
.iter()
.filter(|x| {
if desktopenv == "GNOME" {
x.starts_with("gnome.") || x.starts_with("gnome-")
} else if desktopenv == "XFCE" {
x.starts_with("xfce.")
} else if desktopenv == "MATE" {
x.starts_with("mate.")
} else if desktopenv == "X-Cinnamon" {
x.starts_with("cinnamon.")
} else if desktopenv == "KDE" {
x.starts_with("libsForQt5")
} else if desktopenv == "Pantheon" {
x.starts_with("pantheon.")
} else {
false
}
})
.collect::<Vec<_>>();
for p in desktoppicks.iter().take(3) {
recpicks.push(p.to_string());
let nixpkgsdb = match userpkgs {
UserPkgs::Profile => {
if let Ok(x) = nix_data::cache::profile::nixpkgslatest().await {
Some(x)
} else {
None
}
}
for category in PkgCategory::iter() {
desktoppicks.shuffle(&mut rng);
let mut cvec = vec![];
let mut allvec = vec![];
let mut rpkgs = recommendedpkgs.clone();
fn checkpkgs(
pkg: String,
pkgs: &HashMap<&String, &Package>,
category: PkgCategory,
) -> bool {
match category {
PkgCategory::Audio => {
// Audio:
// - pkgs/applications/audio
if let Some(p) = pkgs.get(&pkg) {
if let Some(pos) = &p.meta.position {
if pos.starts_with("pkgs/applications/audio") {
UserPkgs::Env => None,
};
let systemdb = match syspkgs {
SystemPkgs::None => None,
SystemPkgs::Legacy => {
if let Ok(x) = nix_data::cache::channel::legacypkgs().await {
Some(x)
} else {
None
}
}
SystemPkgs::Flake => {
if let Ok(x) = nix_data::cache::flakes::flakespkgs().await {
Some(x)
} else {
None
}
}
};
let pkglist: Vec<(String,)> = sqlx::query_as("SELECT attribute FROM pkgs")
.fetch_all(&pool)
.await
.unwrap();
let pkglist = pkglist.iter().map(|x| x.0.clone()).collect::<Vec<String>>();
let posvec: Vec<(String, String)> =
sqlx::query_as("SELECT attribute, position FROM meta")
.fetch_all(&pool)
.await
.unwrap();
println!("Got DB data");
let appdata = appsteamdata().unwrap();
let desktopenv = env::var("XDG_CURRENT_DESKTOP").unwrap_or_default();
let mut recpkgs = pkglist
.iter()
.filter(|x| {
if let Some(data) = appdata.get(&x.to_string()) {
(if let Some(i) = &data.icon {
i.cached.is_some()
} else {
false
}) && data.description.is_some()
&& data.name.is_some()
&& data.launchable.is_some()
&& data.screenshots.is_some()
&& (!x.starts_with("gnome.") || desktopenv == "GNOME")
&& (!x.starts_with("xfce.") || desktopenv == "XFCE")
&& (!x.starts_with("mate.") || desktopenv == "MATE")
&& (!x.starts_with("cinnamon.") || desktopenv == "X-Cinnamon")
&& (!x.starts_with("libsForQt5") || desktopenv == "KDE")
&& (!x.starts_with("pantheon.") || desktopenv == "Pantheon")
} else {
false
}
})
.collect::<Vec<_>>();
let mut rng = thread_rng();
recpkgs.shuffle(&mut rng);
let mut desktoppicks = recpkgs
.iter()
.filter(|x| {
if desktopenv == "GNOME" {
x.starts_with("gnome.") || x.starts_with("gnome-")
} else if desktopenv == "XFCE" {
x.starts_with("xfce.")
} else if desktopenv == "MATE" {
x.starts_with("mate.")
} else if desktopenv == "X-Cinnamon" {
x.starts_with("cinnamon.")
} else if desktopenv == "KDE" {
x.starts_with("libsForQt5")
} else if desktopenv == "Pantheon" {
x.starts_with("pantheon.")
} else {
false
}
})
.collect::<Vec<_>>();
for p in desktoppicks.iter().take(3) {
recpicks.push(p.to_string());
}
let pospkgs = posvec
.into_iter()
.map(|(x, y)| (x, if y.is_empty() { None } else { Some(y) }))
.collect::<HashMap<String, Option<String>>>();
println!("Starting category");
for category in vec![
PkgCategory::Audio,
PkgCategory::Development,
PkgCategory::Games,
PkgCategory::Graphics,
PkgCategory::Web,
PkgCategory::Video,
] {
desktoppicks.shuffle(&mut rng);
let mut cvec = vec![];
let mut allvec = vec![];
let mut rpkgs = recpkgs.clone();
fn checkpkgs(
pkg: String,
pospkgs: &HashMap<String, Option<String>>,
appdata: &HashMap<String, AppData>,
category: PkgCategory,
) -> bool {
match category {
PkgCategory::Audio => {
// Audio:
// - pkgs/applications/audio
if let Some(Some(pos)) = pospkgs.get(&pkg) {
if pos.starts_with("pkgs/applications/audio") {
return true;
}
if let Some(data) = appdata.get(&pkg) {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Audio")) {
return true;
}
}
if let Some(data) = &p.appdata {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Audio")) {
return true;
}
}
}
}
false
}
PkgCategory::Development => {
// Development:
// - pkgs/development
// - pkgs/applications/terminal-emulators
// - xdg: Development
if let Some(p) = pkgs.get(&pkg) {
if let Some(pos) = &p.meta.position {
if pos.starts_with("pkgs/development")
|| pos.starts_with(
"pkgs/applications/terminal-emulators",
)
false
}
PkgCategory::Development => {
// Development:
// - pkgs/development
// - pkgs/applications/terminal-emulators
// - xdg: Development
if let Some(Some(pos)) = pospkgs.get(&pkg) {
if pos.starts_with("pkgs/development")
|| pos
.starts_with("pkgs/applications/terminal-emulators")
{
return true;
}
if let Some(data) = appdata.get(&pkg) {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Development"))
{
return true;
}
}
if let Some(data) = &p.appdata {
if let Some(categories) = &data.categories {
if categories
.contains(&String::from("Development"))
{
return true;
}
}
}
}
false
}
PkgCategory::Games => {
// Games:
// - pkgs/games
// - pkgs/applications/emulators
// - pkgs/tools/games
// - xdg::Games
if let Some(p) = pkgs.get(&pkg) {
if let Some(pos) = &p.meta.position {
if pos.starts_with("pkgs/games")
|| pos.starts_with(
"pkgs/applications/emulators",
)
|| pos.starts_with("pkgs/tools/games")
{
false
}
PkgCategory::Games => {
// Games:
// - pkgs/games
// - pkgs/applications/emulators
// - pkgs/tools/games
// - xdg::Games
if let Some(Some(pos)) = pospkgs.get(&pkg) {
if pos.starts_with("pkgs/games")
|| pos.starts_with("pkgs/applications/emulators")
|| pos.starts_with("pkgs/tools/games")
{
return true;
}
if let Some(data) = &appdata.get(&pkg) {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Games")) {
return true;
}
}
if let Some(data) = &p.appdata {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Games")) {
return true;
}
}
}
}
false
}
PkgCategory::Graphics => {
// Graphics:
// - pkgs/applications/graphics
// - xdg: Graphics
if let Some(p) = pkgs.get(&pkg) {
if let Some(pos) = &p.meta.position {
if pos.starts_with("pkgs/applications/graphics")
|| pos.starts_with("xdg:Graphics")
{
false
}
PkgCategory::Graphics => {
// Graphics:
// - pkgs/applications/graphics
// - xdg: Graphics
if let Some(Some(pos)) = pospkgs.get(&pkg) {
if pos.starts_with("pkgs/applications/graphics")
|| pos.starts_with("xdg:Graphics")
{
return true;
}
if let Some(data) = &appdata.get(&pkg) {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Graphics")) {
return true;
}
}
if let Some(data) = &p.appdata {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Graphics")) {
return true;
}
}
}
}
false
}
PkgCategory::Network => {
// Network:
// - pkgs/applications/networking
// - xdg: Network
if let Some(p) = pkgs.get(&pkg) {
if let Some(pos) = &p.meta.position {
if pos.starts_with("pkgs/applications/networking")
|| pos.starts_with("xdg:Network")
{
return true;
}
}
if let Some(data) = &p.appdata {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Network")) {
return true;
}
}
}
}
false
}
PkgCategory::Video => {
// Video:
// - pkgs/applications/video
// - xdg: Video
if let Some(p) = pkgs.get(&pkg) {
if let Some(pos) = &p.meta.position {
if pos.starts_with("pkgs/applications/video")
|| pos.starts_with("xdg:Video")
{
return true;
}
}
if let Some(data) = &p.appdata {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Video")) {
return true;
}
}
}
}
false
}
false
}
PkgCategory::Web => {
// Web:
// - pkgs/applications/networking
// - xdg: Network
if let Some(Some(pos)) = pospkgs.get(&pkg) {
if pos.starts_with("pkgs/applications/networking")
|| pos.starts_with("xdg:Network")
{
return true;
}
if let Some(data) = &appdata.get(&pkg) {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Network")) {
return true;
}
}
}
}
false
}
PkgCategory::Video => {
// Video:
// - pkgs/applications/video
// - xdg: Video
if let Some(Some(pos)) = pospkgs.get(&pkg) {
if pos.starts_with("pkgs/applications/video")
|| pos.starts_with("xdg:Video")
{
return true;
}
if let Some(data) = &appdata.get(&pkg) {
if let Some(categories) = &data.categories {
if categories.contains(&String::from("Video")) {
return true;
}
}
}
}
false
}
}
}
for pkg in desktoppicks.iter().take(3) {
if checkpkgs(pkg.to_string(), &appdatapkgs, category.clone()) {
for pkg in desktoppicks.iter().take(3) {
if checkpkgs(pkg.to_string(), &pospkgs, &appdata, category.clone()) {
cvec.push(pkg.to_string());
}
}
while cvec.len() < 12 {
if let Some(pkg) = rpkgs.pop() {
if !cvec.contains(&pkg.to_string())
&& checkpkgs(
pkg.to_string(),
&pospkgs,
&appdata,
category.clone(),
)
{
cvec.push(pkg.to_string());
}
}
while cvec.len() < 12 {
if let Some(pkg) = rpkgs.pop() {
if !cvec.contains(&pkg.to_string())
&& checkpkgs(
pkg.to_string(),
&appdatapkgs,
category.clone(),
)
{
cvec.push(pkg.to_string());
}
} else {
break;
}
}
let catagortypkgs = pkgs
.iter()
.filter(|(x, _)| {
if let Some(p) = appdatapkgs.get(*x) {
if let Some(position) = &p.meta.position {
(position.starts_with("pkgs/applications/audio") && category == PkgCategory::Audio)
|| (position.starts_with("pkgs/applications/terminal-emulators") && category == PkgCategory::Development)
|| (position.starts_with("pkgs/applications/emulators") && category == PkgCategory::Games)
|| (position.starts_with("pkgs/applications/graphics") && category == PkgCategory::Graphics)
|| (position.starts_with("pkgs/applications/networking") && category == PkgCategory::Network)
|| (position.starts_with("pkgs/applications/video") && category == PkgCategory::Video)
|| (position.starts_with("pkgs/tools/games") && category == PkgCategory::Games)
|| (position.starts_with("pkgs/games") && category == PkgCategory::Games)
|| (position.starts_with("pkgs/development") && category == PkgCategory::Development)
|| appdatapkgs.contains_key(x)
} else {
false
}
} else {
false
}
})
.collect::<HashMap<_, _>>();
for pkg in catagortypkgs.keys() {
if checkpkgs(pkg.to_string(), &catagortypkgs, category.clone()) {
allvec.push(pkg.to_string());
}
}
cvec.shuffle(&mut rng);
allvec.sort_by_key(|x| x.to_lowercase());
catpicks.insert(category.clone(), cvec);
catpkgs.insert(category.clone(), allvec);
}
while recpicks.len() < 12 {
if let Some(p) = recommendedpkgs.pop() {
if !recpicks.contains(&p.to_string()) {
recpicks.push(p);
}
} else {
break;
}
}
recpicks.shuffle(&mut rng);
let catagortypkgs = pkglist
.iter()
.filter(|x| {
if appdata.get(*x).is_some() {
if let Some(Some(position)) = &pospkgs.get(*x) {
(position.starts_with("pkgs/applications/audio")
&& category == PkgCategory::Audio)
|| (position.starts_with(
"pkgs/applications/terminal-emulators",
) && category == PkgCategory::Development)
|| (position.starts_with("pkgs/applications/emulators")
&& category == PkgCategory::Games)
|| (position.starts_with("pkgs/applications/graphics")
&& category == PkgCategory::Graphics)
|| (position
.starts_with("pkgs/applications/networking")
&& category == PkgCategory::Web)
|| (position.starts_with("pkgs/applications/video")
&& category == PkgCategory::Video)
|| (position.starts_with("pkgs/tools/games")
&& category == PkgCategory::Games)
|| (position.starts_with("pkgs/games")
&& category == PkgCategory::Games)
|| (position.starts_with("pkgs/development")
&& category == PkgCategory::Development)
|| recpkgs.contains(x)
} else {
false
}
} else {
false
}
})
.collect::<Vec<_>>();
for pkg in catagortypkgs {
if checkpkgs(pkg.to_string(), &pospkgs, &appdata, category.clone()) {
allvec.push(pkg.to_string());
}
}
cvec.shuffle(&mut rng);
allvec.sort_by_key(|x| x.to_lowercase());
catpicks.insert(category.clone(), cvec);
catpkgs.insert(category.clone(), allvec);
}
match cr {
CacheReturn::Init => {
sender.output(AppMsg::Initialize(pkgs, recpicks, newpkgs, catpicks, catpkgs, profilepkgs));
}
CacheReturn::Update => {
sender.output(AppMsg::ReloadUpdateItems(pkgs, newpkgs));
while recpicks.len() < 12 {
if let Some(p) = recpkgs.pop() {
if !recpicks.contains(&p.to_string()) {
recpicks.push(p.to_string());
}
} else {
break;
}
}
recpicks.shuffle(&mut rng);
sender.output(AppMsg::Initialize(
pkgdb, nixpkgsdb, systemdb, appdata, recpicks, catpicks, catpkgs,
));
});
}
}
@ -435,12 +393,11 @@ pub enum LoadErrorMsg {
Show(String, String),
Retry,
Close,
// Preferences,
}
#[relm4::component(pub)]
impl SimpleComponent for LoadErrorModel {
type InitParams = gtk::Window;
type Init = gtk::Window;
type Input = LoadErrorMsg;
type Output = AppMsg;
type Widgets = LoadErrorWidgets;
@ -472,7 +429,7 @@ impl SimpleComponent for LoadErrorModel {
}
fn init(
parent_window: Self::InitParams,
parent_window: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {