1
0
mirror of https://github.com/IceWhaleTech/CasaOS.git synced 2025-07-15 23:54:17 +02:00

New Feature

- [Apps] This is a feature that has been highly requested by the community. Import the original Docker application into CasaOS. Now it's easy to import with just a few clicks!
- [Apps] App list supports a custom sorting function! You can arrange apps in different orders by dragging the icons.
- [Apps] App custom installation supports Docker Compose configuration import in YAML format.
- [Files] Added thumbnail preview function for image files.
- [Connect] Multiple CasaConenct devices in the LAN will be transmitted through the LAN network.
- [System] Added a switch for auto-mounting USB disk devices.

🎈 Enhancement
- [System] Optimized the system update alert, you will see the new version update log from the next version.
- [Apps] Added live preview for icons in custom installed apps.
- [Apps] Optimized the input of WebUI.
- [Files] Completely updated the image preview, now it supports switching all images in the same folder, as well as dragging, zooming, rotating and resetting.
- [Widgets] Added color levels for CPU and RAM charts.
- [Conenct] Optimized the display of the right-click menu of the Connect friends list.

🎈 Changed
- [Files] Change the initial display directory to /DATA

🐞 Fixed
- [System] Fixed an issue with Raspberry Pi devices failing to boot using USB disks. (Achieved by disabling USB disk auto-mount)
- [Apps] Fixed the issue that some Docker CLI commands failed to import.
- [Apps] Fixed the issue that the app is not easily recognized in /DATA/AppData directory and docker command line after installation, it will be shown as the app name. (Newly installed apps only)
- [Apps] Fixed the issue that Pi-hole cannot be launched after installation in the app store.
- [Apps] Fixed the issue that apps cannot be updated with WatchTower.
- [Files] Fixed the issue that when there is an upload task, the task status is lost after closing Files.
This commit is contained in:
LinkLeong
2022-05-13 18:12:26 +08:00
parent 92d085acf9
commit d0f3dc806e
72 changed files with 9384 additions and 9002 deletions

View File

@ -283,7 +283,6 @@ func CopyDir(src string, dst string) error {
return nil
}
//文件写入临时目录
func WriteToPath(data []byte, path, name string) error {
fullPath := path
if strings.HasSuffix(path, "/") {

View File

@ -42,7 +42,9 @@ func GetThumbnailByOwnerPhotos(path string) ([]byte, error) {
break
}
}
if err != nil {
return nil, err
}
im, err := exifcommon.NewIfdMappingWithStandard()
if err != nil {
return nil, err
@ -54,8 +56,8 @@ func GetThumbnailByOwnerPhotos(path string) ([]byte, error) {
}
ifd := index.RootIfd.NextIfd()
if err != nil {
return nil, err
if ifd == nil {
return nil, exif.ErrNoThumbnail
}
thumbnail, err := ifd.Thumbnail()
if err != nil {

View File

@ -27,6 +27,7 @@ func Get(url string, head map[string]string) (response string) {
}
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
//需要错误日志的处理
//loger.Error(error)
return ""

View File

@ -0,0 +1,30 @@
/*
* @Author: LinkLeong a624669980@163.com
* @Date: 2022-05-08 14:58:46
* @LastEditors: LinkLeong a624669980@163.com
* @LastEditTime: 2022-05-09 13:42:26
* @FilePath: /CasaOS/pkg/utils/network_detection.go
* @Description:
*
* Copyright (c) 2022 by LinkLeong a624669980@163.com, All Rights Reserved.
*/
package utils
import natType "github.com/Curtis-Milo/nat-type-identifier-go"
/**
* @description:
* @param {chanstring} data
* @param {string} url
* @return {*}
*/
func GetNetWorkTypeDetection(data chan string, url string) {
// fmt.Println("url:", url)
// httper.Get(url, nil)
// aaa <- url
result, err := natType.GetDeterminedNatType(true, 5, url)
if err == nil {
data <- result
}
}

View File

@ -0,0 +1,29 @@
/*
* @Author: LinkLeong a624669980@163.com
* @Date: 2022-05-08 15:07:31
* @LastEditors: LinkLeong a624669980@163.com
* @LastEditTime: 2022-05-09 11:43:30
* @FilePath: /CasaOS/pkg/utils/network_detection_test.go
* @Description:
*
* Copyright (c) 2022 by LinkLeong a624669980@163.com, All Rights Reserved.
*/
package utils
import (
"fmt"
"testing"
)
func TestGetResultTest(t *testing.T) {
list := []string{"https://www.google.com", "https://www.bing.com", "https://www.baidu.com"}
data := make(chan string)
//data <- "init"
for _, v := range list {
go GetNetWorkTypeDetection(data, v)
}
result := <-data
close(data)
fmt.Println(result)
}

View File

@ -1,73 +0,0 @@
package sort
import (
"github.com/IceWhaleTech/CasaOS/model"
"sort"
)
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
type devSorter struct {
dev []model.Devices
less []lessFuncDev
}
// sort接口方法之一(Less)
type lessFuncDev func(p1, p2 *model.Devices) bool
// Sort 函数有两个作用
// 第一, 将参数(实际的数据集)赋值给ms对象
// 第二, 调用内置sort函数进行排序操作
func (ms *devSorter) Sort(dev []model.Devices) {
ms.dev = dev
sort.Sort(ms)
}
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
func DevSort(less ...lessFuncDev) *devSorter {
return &devSorter{
less: less,
}
}
// Len 为sort接口方法之一
func (ms *devSorter) Len() int {
return len(ms.dev)
}
// Swap 为sort接口方法之一
func (ms *devSorter) Swap(i, j int) {
ms.dev[i], ms.dev[j] = ms.dev[j], ms.dev[i]
}
// Less 为sort接口方法之一
func (ms *devSorter) Less(i, j int) bool {
temp := ms.dev
p, q := &temp[i], &temp[j]
// Try all but the last comparison.
var k int
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
for k = 0; k < len(ms.less)-1; k++ {
// 提取比较函数, 将函数赋值到新的变量中以便调用
less := ms.less[k]
switch {
case less(p, q):
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
// 如果 p > q, 返回值为false, 则调到下一个case中处理
return true
case less(q, p):
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
return false
}
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
continue
}
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
// 直接返回最后一次的比较结果数据即可
return ms.less[k](p, q)
}

View File

@ -1,74 +0,0 @@
package sort
import (
"sort"
"github.com/IceWhaleTech/CasaOS/model"
)
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
type evnSorter struct {
evn []model.Envs
less []lessFuncEnv
}
// sort接口方法之一(Less)
type lessFuncEnv func(p1, p2 *model.Envs) bool
// Sort 函数有两个作用
// 第一, 将参数(实际的数据集)赋值给ms对象
// 第二, 调用内置sort函数进行排序操作
func (ms *evnSorter) Sort(env []model.Envs) {
ms.evn = env
sort.Sort(ms)
}
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
func EnvSort(less ...lessFuncEnv) *evnSorter {
return &evnSorter{
less: less,
}
}
// Len 为sort接口方法之一
func (ms *evnSorter) Len() int {
return len(ms.evn)
}
// Swap 为sort接口方法之一
func (ms *evnSorter) Swap(i, j int) {
ms.evn[i], ms.evn[j] = ms.evn[j], ms.evn[i]
}
// Less 为sort接口方法之一
func (ms *evnSorter) Less(i, j int) bool {
temp := ms.evn
p, q := &temp[i], &temp[j]
// Try all but the last comparison.
var k int
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
for k = 0; k < len(ms.less)-1; k++ {
// 提取比较函数, 将函数赋值到新的变量中以便调用
less := ms.less[k]
switch {
case less(p, q):
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
// 如果 p > q, 返回值为false, 则调到下一个case中处理
return true
case less(q, p):
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
return false
}
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
continue
}
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
// 直接返回最后一次的比较结果数据即可
return ms.less[k](p, q)
}

View File

@ -1,73 +0,0 @@
package sort
import (
"github.com/IceWhaleTech/CasaOS/model"
"sort"
)
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
type multiSorter struct {
ports []model.Ports
less []lessFunc
}
// sort接口方法之一(Less)
type lessFunc func(p1, p2 *model.Ports) bool
// Sort 函数有两个作用
// 第一, 将参数(实际的数据集)赋值给ms对象
// 第二, 调用内置sort函数进行排序操作
func (ms *multiSorter) Sort(ports []model.Ports) {
ms.ports = ports
sort.Sort(ms)
}
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
func PortsSort(less ...lessFunc) *multiSorter {
return &multiSorter{
less: less,
}
}
// Len 为sort接口方法之一
func (ms *multiSorter) Len() int {
return len(ms.ports)
}
// Swap 为sort接口方法之一
func (ms *multiSorter) Swap(i, j int) {
ms.ports[i], ms.ports[j] = ms.ports[j], ms.ports[i]
}
// Less 为sort接口方法之一
func (ms *multiSorter) Less(i, j int) bool {
port := ms.ports
p, q := &port[i], &port[j]
// Try all but the last comparison.
var k int
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
for k = 0; k < len(ms.less)-1; k++ {
// 提取比较函数, 将函数赋值到新的变量中以便调用
less := ms.less[k]
switch {
case less(p, q):
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
// 如果 p > q, 返回值为false, 则调到下一个case中处理
return true
case less(q, p):
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
return false
}
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
continue
}
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
// 直接返回最后一次的比较结果数据即可
return ms.less[k](p, q)
}

View File

@ -1,73 +0,0 @@
package sort
import (
"github.com/IceWhaleTech/CasaOS/model"
"sort"
)
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
// 而是 []func(p1, p2 *Change) bool 因为在第一个比较的值相等的情况下, 还要比较第二个值, 所以这里需要多个比较函数
type volSorter struct {
vol []model.Volume
less []lessFuncVol
}
// sort接口方法之一(Less)
type lessFuncVol func(p1, p2 *model.Volume) bool
// Sort 函数有两个作用
// 第一, 将参数(实际的数据集)赋值给ms对象
// 第二, 调用内置sort函数进行排序操作
func (ms *volSorter) Sort(vol []model.Volume) {
ms.vol = vol
sort.Sort(ms)
}
// OrderedBy 函数的作用是返回一个multiSorter实例, 并将所有的实际排序函数赋值给实例的less字段,
// 上面已经为multiSorter结构体定义了Sort方法, 所以该函数的返回值可以直接调用Sort方法进行排序
// 该函数中, 为multiSorter结构体中的less字段赋值, Sort方法中又将实际数据集传入, 赋值给multiSorter的ports字段
// 一个函数, 一个方法调用过后, multiSorter实例中两个字段就已经全部被正确赋值, 可以调用系统sort函数进行排序
// 该函数也可看作是一个工厂方法, 用来生成less字段已经被赋值的multiSorter实例
func VolSort(less ...lessFuncVol) *volSorter {
return &volSorter{
less: less,
}
}
// Len 为sort接口方法之一
func (ms *volSorter) Len() int {
return len(ms.vol)
}
// Swap 为sort接口方法之一
func (ms *volSorter) Swap(i, j int) {
ms.vol[i], ms.vol[j] = ms.vol[j], ms.vol[i]
}
// Less 为sort接口方法之一
func (ms *volSorter) Less(i, j int) bool {
temp := ms.vol
p, q := &temp[i], &temp[j]
// Try all but the last comparison.
var k int
// 由于可能有多个需要排序的字段, 也就对应了多个less函数, 当第一个字段的值相等时,
// 需要依次尝试比对后续其他字段的值得大小, 所以这里需要获取比较函数的长度, 以便遍历比较
for k = 0; k < len(ms.less)-1; k++ {
// 提取比较函数, 将函数赋值到新的变量中以便调用
less := ms.less[k]
switch {
case less(p, q):
// 如果 p < q, 返回值为true, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
// 如果 p > q, 返回值为false, 则调到下一个case中处理
return true
case less(q, p):
// 如果 p > q, 返回值为false, 不存在两个值相等需要比较后续字段的情况, 所以这里直接返回
return false
}
// 如果代码走到这里, 说明ms.less[k]函数比较后 p == q; 重新开始下一次循环, 更换到下一个比较函数处理
continue
}
// 如果代码走到这里, 说明所有的比较函数执行过后, 所有比较的值都相等
// 直接返回最后一次的比较结果数据即可
return ms.less[k](p, q)
}