Implement Redis caching for S3 list object calls
This commit is contained in:
@ -8,7 +8,6 @@ import (
|
||||
"github.com/fossyy/filekeeper/utils"
|
||||
fileView "github.com/fossyy/filekeeper/view/client/file"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GET(w http.ResponseWriter, r *http.Request) {
|
||||
@ -22,26 +21,14 @@ func GET(w http.ResponseWriter, r *http.Request) {
|
||||
var filesData []types.FileData
|
||||
|
||||
for _, file := range files {
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", file.OwnerID.String(), file.ID.String())
|
||||
|
||||
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
|
||||
userFile, err := app.Server.Service.GetUserFile(r.Context(), file.Name, file.OwnerID.String())
|
||||
if err != nil {
|
||||
app.Server.Logger.Error(err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
missingChunk := len(existingChunks) != int(file.TotalChunk)
|
||||
|
||||
filesData = append(filesData, types.FileData{
|
||||
ID: file.ID.String(),
|
||||
Name: file.Name,
|
||||
Size: utils.ConvertFileSize(file.Size),
|
||||
IsPrivate: file.IsPrivate,
|
||||
Type: file.Type,
|
||||
Done: !missingChunk,
|
||||
Downloaded: strconv.FormatUint(file.Downloaded, 10),
|
||||
})
|
||||
filesData = append(filesData, *userFile)
|
||||
}
|
||||
|
||||
allowance, err := app.Server.Database.GetAllowance(userSession.UserID)
|
||||
@ -50,7 +37,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
|
||||
app.Server.Logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
usage, err := app.Server.Service.GetUserStorageUsage(userSession.UserID.String())
|
||||
usage, err := app.Server.Service.GetUserStorageUsage(r.Context(), userSession.UserID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
|
@ -1,13 +1,10 @@
|
||||
package queryHandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fossyy/filekeeper/app"
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
"github.com/fossyy/filekeeper/utils"
|
||||
fileView "github.com/fossyy/filekeeper/view/client/file"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func GET(w http.ResponseWriter, r *http.Request) {
|
||||
@ -34,26 +31,14 @@ func GET(w http.ResponseWriter, r *http.Request) {
|
||||
var filesData []types.FileData
|
||||
|
||||
for _, file := range files {
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", file.OwnerID.String(), file.ID.String())
|
||||
|
||||
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
|
||||
userFile, err := app.Server.Service.GetUserFile(r.Context(), file.Name, file.OwnerID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
missingChunk := len(existingChunks) != int(file.TotalChunk)
|
||||
|
||||
filesData = append(filesData, types.FileData{
|
||||
ID: file.ID.String(),
|
||||
Name: file.Name,
|
||||
Size: utils.ConvertFileSize(file.Size),
|
||||
IsPrivate: file.IsPrivate,
|
||||
Type: file.Type,
|
||||
Done: !missingChunk,
|
||||
Downloaded: strconv.FormatUint(file.Downloaded, 10),
|
||||
})
|
||||
filesData = append(filesData, *userFile)
|
||||
}
|
||||
|
||||
if r.Header.Get("hx-request") == "true" {
|
||||
|
@ -1,13 +1,10 @@
|
||||
package renameFileHandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fossyy/filekeeper/app"
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
"github.com/fossyy/filekeeper/utils"
|
||||
fileView "github.com/fossyy/filekeeper/view/client/file"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func PATCH(w http.ResponseWriter, r *http.Request) {
|
||||
@ -39,28 +36,14 @@ func PATCH(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", file.OwnerID.String(), file.ID.String())
|
||||
|
||||
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
|
||||
userFile, err := app.Server.Service.GetUserFile(r.Context(), newFile.Name, newFile.OwnerID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
missingChunk := len(existingChunks) != int(file.TotalChunk)
|
||||
|
||||
fileData := types.FileData{
|
||||
ID: newFile.ID.String(),
|
||||
Name: newFile.Name,
|
||||
Size: utils.ConvertFileSize(newFile.Size),
|
||||
IsPrivate: newFile.IsPrivate,
|
||||
Type: newFile.Type,
|
||||
Done: !missingChunk,
|
||||
Downloaded: strconv.FormatUint(newFile.Downloaded, 10),
|
||||
}
|
||||
|
||||
component := fileView.JustFile(fileData)
|
||||
component := fileView.JustFile(*userFile)
|
||||
err = component.Render(r.Context(), w)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -16,7 +16,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
file, err := app.Server.Service.GetFile(fileID)
|
||||
file, err := app.Server.Service.GetFile(r.Context(), fileID)
|
||||
if err != nil {
|
||||
app.Server.Logger.Error("error getting upload info: " + err.Error())
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@ -52,7 +52,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
|
||||
app.Server.Logger.Error("error copying byte to file dst: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
app.Server.Service.UpdateFileChunk(r.Context(), file.ID, file.OwnerID, rawIndex, file.TotalChunk)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
return
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
package visibilityHandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fossyy/filekeeper/app"
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
"github.com/fossyy/filekeeper/utils"
|
||||
fileView "github.com/fossyy/filekeeper/view/client/file"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func PUT(w http.ResponseWriter, r *http.Request) {
|
||||
@ -32,26 +29,13 @@ func PUT(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", file.OwnerID.String(), file.ID.String())
|
||||
|
||||
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
|
||||
userFile, err := app.Server.Service.GetUserFile(r.Context(), file.Name, file.OwnerID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
missingChunk := len(existingChunks) != int(file.TotalChunk)
|
||||
fileData := types.FileData{
|
||||
ID: file.ID.String(),
|
||||
Name: file.Name,
|
||||
Size: utils.ConvertFileSize(file.Size),
|
||||
IsPrivate: !file.IsPrivate,
|
||||
Type: file.Type,
|
||||
Done: !missingChunk,
|
||||
Downloaded: strconv.FormatUint(file.Downloaded, 10),
|
||||
}
|
||||
component := fileView.JustFile(fileData)
|
||||
component := fileView.JustFile(*userFile)
|
||||
err = component.Render(r.Context(), w)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -122,7 +122,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = app.Server.Service.DeleteUser(userData.User.Email)
|
||||
err = app.Server.Service.DeleteUser(r.Context(), userData.User.Email)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
|
@ -51,7 +51,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = app.Server.Service.DeleteUser(userSession.Email)
|
||||
err = app.Server.Service.DeleteUser(r.Context(), userSession.Email)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
|
@ -87,7 +87,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
|
||||
app.Server.Logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
err := app.Server.Service.DeleteUser(userSession.Email)
|
||||
err := app.Server.Service.DeleteUser(r.Context(), userSession.Email)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
|
@ -76,7 +76,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
usage, err := app.Server.Service.GetUserStorageUsage(userSession.UserID.String())
|
||||
usage, err := app.Server.Service.GetUserStorageUsage(r.Context(), userSession.UserID.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
app.Server.Logger.Error(err.Error())
|
||||
@ -178,8 +178,9 @@ func handlerWS(conn *websocket.Conn, userSession types.User) {
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
fileID := uuid.New()
|
||||
newFile := models.File{
|
||||
ID: uuid.New(),
|
||||
ID: fileID,
|
||||
OwnerID: userSession.UserID,
|
||||
Name: uploadNewFile.Name,
|
||||
Size: uploadNewFile.Size,
|
||||
@ -189,42 +190,24 @@ func handlerWS(conn *websocket.Conn, userSession types.User) {
|
||||
TotalChunk: uploadNewFile.Chunk,
|
||||
Downloaded: 0,
|
||||
}
|
||||
|
||||
err := app.Server.Database.CreateFile(&newFile)
|
||||
if err != nil {
|
||||
sendErrorResponse(conn, action.Action, "Error Creating File")
|
||||
continue
|
||||
}
|
||||
fileData := &types.FileWithDetail{
|
||||
ID: newFile.ID,
|
||||
OwnerID: newFile.OwnerID,
|
||||
Name: newFile.Name,
|
||||
Size: newFile.Size,
|
||||
Downloaded: newFile.Downloaded,
|
||||
Done: false,
|
||||
}
|
||||
fileData.Chunk = make(map[string]bool)
|
||||
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", userSession.UserID.String(), newFile.ID.String())
|
||||
|
||||
existingChunks, err := app.Server.Storage.ListObjects(context.TODO(), prefix)
|
||||
userFile, err := app.Server.Service.GetUserFile(context.Background(), uploadNewFile.Name, userSession.UserID.String())
|
||||
if err != nil {
|
||||
app.Server.Logger.Error(err.Error())
|
||||
sendErrorResponse(conn, action.Action, "Unknown error")
|
||||
continue
|
||||
} else {
|
||||
for i := 0; i < int(newFile.TotalChunk); i++ {
|
||||
fileData.Chunk[fmt.Sprintf("chunk_%d", i)] = false
|
||||
}
|
||||
|
||||
for _, chunkFile := range existingChunks {
|
||||
var chunkIndex int
|
||||
fmt.Sscanf(chunkFile, "chunk_%d", &chunkIndex)
|
||||
fileData.Chunk[fmt.Sprintf("chunk_%d", chunkIndex)] = true
|
||||
}
|
||||
}
|
||||
sendSuccessResponseWithID(conn, action.Action, fileData, uploadNewFile.RequestID)
|
||||
|
||||
sendSuccessResponseWithID(conn, action.Action, userFile, uploadNewFile.RequestID)
|
||||
continue
|
||||
} else {
|
||||
app.Server.Logger.Error(err.Error())
|
||||
sendErrorResponse(conn, action.Action, "Unknown error")
|
||||
continue
|
||||
}
|
||||
@ -233,40 +216,14 @@ func handlerWS(conn *websocket.Conn, userSession types.User) {
|
||||
sendErrorResponse(conn, action.Action, "File Is Different")
|
||||
continue
|
||||
}
|
||||
fileData := &types.FileWithDetail{
|
||||
ID: file.ID,
|
||||
OwnerID: file.OwnerID,
|
||||
Name: file.Name,
|
||||
Size: file.Size,
|
||||
Downloaded: file.Downloaded,
|
||||
Chunk: make(map[string]bool),
|
||||
Done: true,
|
||||
}
|
||||
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", userSession.UserID.String(), file.ID.String())
|
||||
existingChunks, err := app.Server.Storage.ListObjects(context.TODO(), prefix)
|
||||
userFile, err := app.Server.Service.GetUserFile(context.Background(), file.Name, userSession.UserID.String())
|
||||
if err != nil {
|
||||
app.Server.Logger.Error(err.Error())
|
||||
fileData.Done = false
|
||||
} else {
|
||||
for i := 0; i < int(file.TotalChunk); i++ {
|
||||
fileData.Chunk[fmt.Sprintf("chunk_%d", i)] = false
|
||||
}
|
||||
for _, chunkFile := range existingChunks {
|
||||
var chunkIndex int
|
||||
fmt.Sscanf(chunkFile, "chunk_%d", &chunkIndex)
|
||||
fileData.Chunk[fmt.Sprintf("chunk_%d", chunkIndex)] = true
|
||||
}
|
||||
|
||||
for i := 0; i < int(file.TotalChunk); i++ {
|
||||
if !fileData.Chunk[fmt.Sprintf("chunk_%d", i)] {
|
||||
fileData.Done = false
|
||||
break
|
||||
}
|
||||
}
|
||||
sendErrorResponse(conn, action.Action, "Unknown error")
|
||||
continue
|
||||
}
|
||||
|
||||
sendSuccessResponseWithID(conn, action.Action, fileData, uploadNewFile.RequestID)
|
||||
sendSuccessResponseWithID(conn, action.Action, userFile, uploadNewFile.RequestID)
|
||||
continue
|
||||
case Ping:
|
||||
sendSuccessResponse(conn, action.Action, map[string]string{"message": "received"})
|
||||
|
@ -3,9 +3,12 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/fossyy/filekeeper/app"
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
"github.com/fossyy/filekeeper/types/models"
|
||||
"github.com/google/uuid"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"time"
|
||||
)
|
||||
@ -24,29 +27,29 @@ func NewService(db types.Database, cache types.CachingServer) *Service {
|
||||
|
||||
func (r *Service) GetUser(ctx context.Context, email string) (*models.User, error) {
|
||||
userJSON, err := app.Server.Cache.GetCache(ctx, "UserCache:"+email)
|
||||
if err == redis.Nil {
|
||||
userData, err := r.db.GetUser(email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := &models.User{
|
||||
UserID: userData.UserID,
|
||||
Username: userData.Username,
|
||||
Email: userData.Email,
|
||||
Password: userData.Password,
|
||||
Totp: userData.Totp,
|
||||
}
|
||||
|
||||
newUserJSON, _ := json.Marshal(user)
|
||||
err = r.cache.SetCache(ctx, "UserCache:"+email, newUserJSON, time.Hour*12)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
userData, err := r.db.GetUser(email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user := &models.User{
|
||||
UserID: userData.UserID,
|
||||
Username: userData.Username,
|
||||
Email: userData.Email,
|
||||
Password: userData.Password,
|
||||
Totp: userData.Totp,
|
||||
}
|
||||
|
||||
newUserJSON, _ := json.Marshal(user)
|
||||
err = r.cache.SetCache(ctx, "UserCache:"+email, newUserJSON, time.Hour*12)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -59,15 +62,16 @@ func (r *Service) GetUser(ctx context.Context, email string) (*models.User, erro
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (r *Service) DeleteUser(email string) error {
|
||||
err := r.cache.DeleteCache(context.Background(), "UserCache:"+email)
|
||||
func (r *Service) DeleteUser(ctx context.Context, email string) error {
|
||||
err := r.cache.DeleteCache(ctx, "UserCache:"+email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Service) GetUserStorageUsage(ownerID string) (uint64, error) {
|
||||
func (r *Service) GetUserStorageUsage(ctx context.Context, ownerID string) (uint64, error) {
|
||||
// TODO: Implement GetUserStorageUsage Cache
|
||||
files, err := app.Server.Database.GetFiles(ownerID, "", types.All)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@ -79,22 +83,22 @@ func (r *Service) GetUserStorageUsage(ownerID string) (uint64, error) {
|
||||
return total, nil
|
||||
}
|
||||
|
||||
func (r *Service) GetFile(id string) (*models.File, error) {
|
||||
fileJSON, err := r.cache.GetCache(context.Background(), "FileCache:"+id)
|
||||
if err == redis.Nil {
|
||||
uploadData, err := r.db.GetFile(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newFileJSON, _ := json.Marshal(uploadData)
|
||||
err = r.cache.SetCache(context.Background(), "FileCache:"+id, newFileJSON, time.Hour*24)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uploadData, nil
|
||||
}
|
||||
func (r *Service) GetFile(ctx context.Context, id string) (*models.File, error) {
|
||||
fileJSON, err := r.cache.GetCache(ctx, "FileCache:"+id)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
uploadData, err := r.db.GetFile(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newFileJSON, _ := json.Marshal(uploadData)
|
||||
err = r.cache.SetCache(ctx, "FileCache:"+id, newFileJSON, time.Hour*24)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uploadData, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -106,18 +110,141 @@ func (r *Service) GetFile(id string) (*models.File, error) {
|
||||
return &fileCache, nil
|
||||
}
|
||||
|
||||
func (r *Service) GetUserFile(name, ownerID string) (*types.FileWithDetail, error) {
|
||||
fileData, err := r.db.GetUserFile(name, ownerID)
|
||||
func (r *Service) GetFileChunks(ctx context.Context, fileID uuid.UUID, ownerID uuid.UUID, totalChunk uint64) (*types.FileState, error) {
|
||||
fileJSON, err := r.cache.GetCache(ctx, "FileChunkCache:"+fileID.String())
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
prefix := fmt.Sprintf("%s/%s/chunk_", ownerID.String(), fileID.String())
|
||||
|
||||
existingChunks, err := app.Server.Storage.ListObjects(ctx, prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
missingChunk := len(existingChunks) != int(totalChunk)
|
||||
|
||||
newChunkCache := types.FileState{
|
||||
Done: !missingChunk,
|
||||
Chunk: make(map[string]bool),
|
||||
}
|
||||
for i := 0; i < int(totalChunk); i++ {
|
||||
newChunkCache.Chunk[fmt.Sprintf("chunk_%d", i)] = false
|
||||
}
|
||||
|
||||
for _, chunkFile := range existingChunks {
|
||||
var chunkIndex int
|
||||
fmt.Sscanf(chunkFile, "chunk_%d", &chunkIndex)
|
||||
newChunkCache.Chunk[fmt.Sprintf("chunk_%d", chunkIndex)] = true
|
||||
}
|
||||
newChunkCacheJSON, err := json.Marshal(newChunkCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.cache.SetCache(ctx, "FileChunkCache:"+fileID.String(), newChunkCacheJSON, time.Minute*30)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newChunkCache, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dada := &types.FileWithDetail{
|
||||
ID: fileData.ID,
|
||||
OwnerID: fileData.OwnerID,
|
||||
Name: fileData.Name,
|
||||
Size: fileData.Size,
|
||||
Downloaded: fileData.Downloaded,
|
||||
var existingCache types.FileState
|
||||
err = json.Unmarshal([]byte(fileJSON), &existingCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dada, nil
|
||||
return &existingCache, nil
|
||||
}
|
||||
|
||||
func (r *Service) UpdateFileChunk(ctx context.Context, fileID uuid.UUID, ownerID uuid.UUID, chunk string, totalChunk uint64) error {
|
||||
chunks, err := r.GetFileChunks(ctx, fileID, ownerID, totalChunk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chunks.Chunk[fmt.Sprintf("chunk_%s", chunk)] = true
|
||||
chunks.Done = true
|
||||
|
||||
for i := 0; i < int(totalChunk); i++ {
|
||||
if !chunks.Chunk[fmt.Sprintf("chunk_%d", i)] {
|
||||
fmt.Println("chunk", i, " ", chunks.Chunk[fmt.Sprintf("chunk_%d", i)])
|
||||
chunks.Done = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
updatedChunkCacheJSON, err := json.Marshal(chunks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = r.cache.SetCache(ctx, "FileChunkCache:"+fileID.String(), updatedChunkCacheJSON, time.Minute*30)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Service) GetUserFile(ctx context.Context, name, ownerID string) (*types.FileData, error) {
|
||||
cacheKey := "UserFileCache:" + ownerID + ":" + name
|
||||
cachedFileData, err := r.cache.GetCache(ctx, cacheKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
fileData, err := r.db.GetUserFile(name, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chunks, err := r.GetFileChunks(ctx, fileData.ID, fileData.OwnerID, fileData.TotalChunk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := &types.FileData{
|
||||
ID: fileData.ID,
|
||||
OwnerID: fileData.OwnerID,
|
||||
Name: fileData.Name,
|
||||
Size: fileData.Size,
|
||||
TotalChunk: fileData.TotalChunk,
|
||||
StartHash: fileData.StartHash,
|
||||
EndHash: fileData.EndHash,
|
||||
Downloaded: fileData.Downloaded,
|
||||
IsPrivate: fileData.IsPrivate,
|
||||
Type: fileData.Type,
|
||||
Done: chunks.Done,
|
||||
Chunk: chunks.Chunk,
|
||||
}
|
||||
|
||||
fileDataToCache := &types.FileData{
|
||||
ID: fileData.ID,
|
||||
OwnerID: fileData.OwnerID,
|
||||
Name: fileData.Name,
|
||||
Size: fileData.Size,
|
||||
TotalChunk: fileData.TotalChunk,
|
||||
StartHash: fileData.StartHash,
|
||||
EndHash: fileData.EndHash,
|
||||
Downloaded: fileData.Downloaded,
|
||||
IsPrivate: fileData.IsPrivate,
|
||||
Type: fileData.Type,
|
||||
}
|
||||
cachedFileDataJSON, err := json.Marshal(fileDataToCache)
|
||||
if err == nil {
|
||||
_ = r.cache.SetCache(ctx, cacheKey, cachedFileDataJSON, time.Minute*30)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
var fileData types.FileData
|
||||
err = json.Unmarshal([]byte(cachedFileData), &fileData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chunks, err := r.GetFileChunks(ctx, fileData.ID, fileData.OwnerID, fileData.TotalChunk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileData.Done = chunks.Done
|
||||
fileData.Chunk = chunks.Chunk
|
||||
return &fileData, nil
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ type Message struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type Number interface {
|
||||
int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64
|
||||
}
|
||||
|
||||
type User struct {
|
||||
UserID uuid.UUID
|
||||
Email string
|
||||
@ -36,23 +40,23 @@ type Allowance struct {
|
||||
}
|
||||
|
||||
type FileData struct {
|
||||
ID string
|
||||
Name string
|
||||
Size string
|
||||
IsPrivate bool
|
||||
Type string
|
||||
Done bool
|
||||
Downloaded string
|
||||
}
|
||||
|
||||
type FileWithDetail struct {
|
||||
ID uuid.UUID
|
||||
OwnerID uuid.UUID
|
||||
Name string
|
||||
Size uint64
|
||||
TotalChunk uint64
|
||||
StartHash string
|
||||
EndHash string
|
||||
Downloaded uint64
|
||||
Chunk map[string]bool
|
||||
IsPrivate bool
|
||||
Type string
|
||||
Done bool
|
||||
Chunk map[string]bool
|
||||
}
|
||||
|
||||
type FileState struct {
|
||||
Done bool
|
||||
Chunk map[string]bool
|
||||
}
|
||||
|
||||
type Database interface {
|
||||
@ -88,10 +92,12 @@ type CachingServer interface {
|
||||
|
||||
type Services interface {
|
||||
GetUser(ctx context.Context, email string) (*models.User, error)
|
||||
DeleteUser(email string) error
|
||||
GetFile(id string) (*models.File, error)
|
||||
GetUserFile(name, ownerID string) (*FileWithDetail, error)
|
||||
GetUserStorageUsage(ownerID string) (uint64, error)
|
||||
DeleteUser(ctx context.Context, email string) error
|
||||
GetFile(ctx context.Context, id string) (*models.File, error)
|
||||
GetUserFile(ctx context.Context, name, ownerID string) (*FileData, error)
|
||||
GetUserStorageUsage(ctx context.Context, ownerID string) (uint64, error)
|
||||
GetFileChunks(ctx context.Context, fileID uuid.UUID, ownerID uuid.UUID, totalChunk uint64) (*FileState, error)
|
||||
UpdateFileChunk(ctx context.Context, fileID uuid.UUID, ownerID uuid.UUID, chunk string, totalChunk uint64) error
|
||||
}
|
||||
|
||||
type Storage interface {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/fossyy/filekeeper/app"
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
mathRand "math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -87,15 +88,17 @@ func ValidatePassword(password string) bool {
|
||||
return hasNumber && hasUppercase
|
||||
}
|
||||
|
||||
func ConvertFileSize(byte uint64) string {
|
||||
if byte < 1024 {
|
||||
return fmt.Sprintf("%d B", byte)
|
||||
} else if byte < 1024*1024 {
|
||||
return fmt.Sprintf("%d KB", byte/1024)
|
||||
} else if byte < 1024*1024*1024 {
|
||||
return fmt.Sprintf("%d MB", byte/(1024*1024))
|
||||
func ConvertFileSize[T types.Number](size T) string {
|
||||
sizeInBytes := int64(size)
|
||||
|
||||
if sizeInBytes < 1024 {
|
||||
return fmt.Sprintf("%d B", sizeInBytes)
|
||||
} else if sizeInBytes < 1024*1024 {
|
||||
return fmt.Sprintf("%.2f KB", float64(sizeInBytes)/1024)
|
||||
} else if sizeInBytes < 1024*1024*1024 {
|
||||
return fmt.Sprintf("%.2f MB", float64(sizeInBytes)/(1024*1024))
|
||||
} else {
|
||||
return fmt.Sprintf("%d GB", byte/(1024*1024*1024))
|
||||
return fmt.Sprintf("%.2f GB", float64(sizeInBytes)/(1024*1024*1024))
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,3 +208,7 @@ func ParseUserAgent(userAgent string) (map[string]string, map[string]string) {
|
||||
|
||||
return browserInfo, osInfo
|
||||
}
|
||||
|
||||
func IntToString[T types.Number](number T) string {
|
||||
return fmt.Sprintf("%d", number)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package fileView
|
||||
import (
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
"github.com/fossyy/filekeeper/view/client/layout"
|
||||
"github.com/fossyy/filekeeper/utils"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
@ -289,7 +290,7 @@ templ FileTable(files []types.FileData) {
|
||||
}
|
||||
|
||||
templ JustFile(file types.FileData) {
|
||||
<tr id={ "file-" + file.ID } class="bg-white border-b">
|
||||
<tr id={ "file-" + file.ID.String() } class="bg-white border-b">
|
||||
if !file.Done {
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap flex items-center">
|
||||
@FileIcon(file.Type)
|
||||
@ -315,7 +316,7 @@ templ JustFile(file types.FileData) {
|
||||
</div>
|
||||
</td>
|
||||
}
|
||||
<td class="px-6 py-4">{ file.Size }</td>
|
||||
<td class="px-6 py-4">{ utils.ConvertFileSize(file.Size) }</td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-2 text-gray-400">
|
||||
@ -323,7 +324,7 @@ templ JustFile(file types.FileData) {
|
||||
<polyline points="7 10 12 15 17 10"></polyline>
|
||||
<line x1="12" x2="12" y1="15" y2="3"></line>
|
||||
</svg>
|
||||
{ file.Downloaded }
|
||||
{ utils.IntToString(file.Downloaded) }
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
@ -373,12 +374,12 @@ templ JustFile(file types.FileData) {
|
||||
<div class="dropdown-menu hidden absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10">
|
||||
if file.Done {
|
||||
<div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
|
||||
<a href={ templ.SafeURL("/file/" + file.ID) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<a href={ templ.SafeURL("/file/" + file.ID.String()) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" x2="12" y1="15" y2="3"></line></svg>
|
||||
<i class="ri-file-copy-line mr-3 text-gray-400"></i> Download
|
||||
</a>
|
||||
if file.IsPrivate {
|
||||
<button class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem" hx-put={ "/file/" + file.ID } hx-target={ "#file-" + file.ID } hx-swap="outerHTML">
|
||||
<button class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem" hx-put={ "/file/" + file.ID.String() } hx-target={ "#file-" + file.ID.String() } hx-swap="outerHTML">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 text-gray-600"
|
||||
@ -395,7 +396,7 @@ templ JustFile(file types.FileData) {
|
||||
<i class="ri-delete-bin-line mr-3 text-gray-400"></i> Make Public
|
||||
</button>
|
||||
} else {
|
||||
<button class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem" hx-put={ "/file/" + file.ID } hx-target={ "#file-" + file.ID } hx-swap="outerHTML">
|
||||
<button class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem" hx-put={ "/file/" + file.ID.String() } hx-target={ "#file-" + file.ID.String() } hx-swap="outerHTML">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 text-gray-600"
|
||||
@ -412,18 +413,18 @@ templ JustFile(file types.FileData) {
|
||||
<i class="ri-delete-bin-line mr-3 text-gray-400"></i> Make Private
|
||||
</button>
|
||||
}
|
||||
<button onClick={ showShareModal(file.IsPrivate, file.ID) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<button onClick={ showShareModal(file.IsPrivate, file.ID.String()) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-share-2"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" x2="15.42" y1="13.51" y2="17.49"></line><line x1="15.41" x2="8.59" y1="6.51" y2="10.49"></line></svg>
|
||||
<i class="ri-delete-bin-line mr-3 text-gray-400"></i> Share
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
<div class="py-1 border-t" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
|
||||
<button onClick={ showRenameModal(file.Name, file.ID) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<button onClick={ showRenameModal(file.Name, file.ID.String()) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-pen"><path d="M2 11.5V5a2 2 0 0 1 2-2h3.9c.7 0 1.3.3 1.7.9l.8 1.2c.4.6 1 .9 1.7.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-9.5"></path><path d="M11.378 13.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"></path></svg>
|
||||
<i class="ri-share-line mr-3 text-gray-400"></i> Rename
|
||||
</button>
|
||||
<button onClick={ showDeletionModal(file.Name, file.ID) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<button onClick={ showDeletionModal(file.Name, file.ID.String()) } class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 w-full" role="menuitem">
|
||||
<svg width="16px" height="16px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g stroke-width="0"></g><g stroke-linecap="round" stroke-linejoin="round"></g><g><path d="M20.5001 6H3.5" stroke="#000000" stroke-width="1.5" stroke-linecap="round"></path> <path d="M9.5 11L10 16" stroke="#000000" stroke-width="1.5" stroke-linecap="round"></path> <path d="M14.5 11L14 16" stroke="#000000" stroke-width="1.5" stroke-linecap="round"></path> <path d="M6.5 6C6.55588 6 6.58382 6 6.60915 5.99936C7.43259 5.97849 8.15902 5.45491 8.43922 4.68032C8.44784 4.65649 8.45667 4.62999 8.47434 4.57697L8.57143 4.28571C8.65431 4.03708 8.69575 3.91276 8.75071 3.8072C8.97001 3.38607 9.37574 3.09364 9.84461 3.01877C9.96213 3 10.0932 3 10.3553 3H13.6447C13.9068 3 14.0379 3 14.1554 3.01877C14.6243 3.09364 15.03 3.38607 15.2493 3.8072C15.3043 3.91276 15.3457 4.03708 15.4286 4.28571L15.5257 4.57697C15.5433 4.62992 15.5522 4.65651 15.5608 4.68032C15.841 5.45491 16.5674 5.97849 17.3909 5.99936C17.4162 6 17.4441 6 17.5 6" stroke="#000000" stroke-width="1.5"></path> <path d="M18.3735 15.3991C18.1965 18.054 18.108 19.3815 17.243 20.1907C16.378 21 15.0476 21 12.3868 21H11.6134C8.9526 21 7.6222 21 6.75719 20.1907C5.89218 19.3815 5.80368 18.054 5.62669 15.3991L5.16675 8.5M18.8334 8.5L18.6334 11.5" stroke="#000000" stroke-width="1.5" stroke-linecap="round"></path> </g></svg>
|
||||
<i class="ri-clipboard-line mr-3 text-gray-400"></i> Remove
|
||||
</button>
|
||||
|
@ -10,6 +10,7 @@ import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import (
|
||||
"github.com/fossyy/filekeeper/types"
|
||||
"github.com/fossyy/filekeeper/utils"
|
||||
"github.com/fossyy/filekeeper/view/client/layout"
|
||||
"strconv"
|
||||
)
|
||||
@ -89,7 +90,7 @@ func MainContent(title string, files []types.FileData, user types.User, allowanc
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 16, Col: 15}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 17, Col: 15}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -205,7 +206,7 @@ func MainContent(title string, files []types.FileData, user types.User, allowanc
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(len(files)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 204, Col: 88}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 205, Col: 88}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -218,7 +219,7 @@ func MainContent(title string, files []types.FileData, user types.User, allowanc
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(allowance.AllowanceUsedByte)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 205, Col: 91}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 206, Col: 91}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -231,7 +232,7 @@ func MainContent(title string, files []types.FileData, user types.User, allowanc
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(allowance.AllowanceByte)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 206, Col: 91}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 207, Col: 91}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -336,9 +337,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs("file-" + file.ID)
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs("file-" + file.ID.String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 292, Col: 27}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 293, Col: 36}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -364,7 +365,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(file.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 297, Col: 80}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 298, Col: 80}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -377,7 +378,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(file.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 298, Col: 17}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 299, Col: 17}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -403,7 +404,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
var templ_7745c5c3_Var18 string
|
||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(file.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 312, Col: 80}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 313, Col: 80}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -416,7 +417,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(file.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 313, Col: 17}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 314, Col: 17}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -432,9 +433,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var20 string
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(file.Size)
|
||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(utils.ConvertFileSize(file.Size))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 318, Col: 35}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 319, Col: 58}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -445,9 +446,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var21 string
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(file.Downloaded)
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(utils.IntToString(file.Downloaded))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 326, Col: 21}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 327, Col: 40}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -494,7 +495,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var23 templ.SafeURL = templ.SafeURL("/file/" + file.ID)
|
||||
var templ_7745c5c3_Var23 templ.SafeURL = templ.SafeURL("/file/" + file.ID.String())
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var23)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
@ -509,9 +510,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var24 string
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs("/file/" + file.ID)
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs("/file/" + file.ID.String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 381, Col: 162}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 382, Col: 171}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -522,9 +523,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var25 string
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs("#file-" + file.ID)
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs("#file-" + file.ID.String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 381, Col: 195}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 382, Col: 213}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -540,9 +541,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var26 string
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs("/file/" + file.ID)
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs("/file/" + file.ID.String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 398, Col: 162}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 399, Col: 171}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -553,9 +554,9 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var27 string
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs("#file-" + file.ID)
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs("#file-" + file.ID.String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 398, Col: 195}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/client/file/file.templ`, Line: 399, Col: 213}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@ -566,7 +567,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, showShareModal(file.IsPrivate, file.ID))
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, showShareModal(file.IsPrivate, file.ID.String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -574,7 +575,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var28 templ.ComponentScript = showShareModal(file.IsPrivate, file.ID)
|
||||
var templ_7745c5c3_Var28 templ.ComponentScript = showShareModal(file.IsPrivate, file.ID.String())
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
@ -588,7 +589,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, showRenameModal(file.Name, file.ID))
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, showRenameModal(file.Name, file.ID.String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -596,7 +597,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var29 templ.ComponentScript = showRenameModal(file.Name, file.ID)
|
||||
var templ_7745c5c3_Var29 templ.ComponentScript = showRenameModal(file.Name, file.ID.String())
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var29.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
@ -605,7 +606,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, showDeletionModal(file.Name, file.ID))
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, showDeletionModal(file.Name, file.ID.String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -613,7 +614,7 @@ func JustFile(file types.FileData) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var30 templ.ComponentScript = showDeletionModal(file.Name, file.ID)
|
||||
var templ_7745c5c3_Var30 templ.ComponentScript = showDeletionModal(file.Name, file.ID.String())
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var30.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
|
Reference in New Issue
Block a user