Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(filesLimit): handle if user goes over size limit #1715

Merged
merged 11 commits into from
Mar 4, 2022
Merged
2 changes: 1 addition & 1 deletion components/ui/Progress/Progress.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<template src="./Progress.html" />
<template src="./Progress.html"></template>
<script lang="ts">
import Vue from 'vue'

Expand Down
6 changes: 4 additions & 2 deletions components/views/files/aside/Aside.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
:data-tooltip="$t('pages.files.aside.coming_soon')"
/>
</div>
<UiProgress :progress="80" />
<UiProgress :progress="progress" />
<div>
<span class="usage-text"> <span class="red">3.8GB</span> of 4GB </span>
<span class="usage-text">
<span :class="sizeColor">{{totalSize}}</span> of {{sizeLimit}}
</span>
</div>
<UiSpacer :height="10" />
<div>
Expand Down
26 changes: 24 additions & 2 deletions components/views/files/aside/Aside.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
<template src="./Aside.html" />
<template src="./Aside.html"></template>
<script lang="ts">
import Vue from 'vue'

export default Vue.extend({})
export default Vue.extend({
data() {
return {
progress: this.$FileSystem.percentStorageUsed as number,
}
},
computed: {
totalSize(): string {
return this.$filesize(this.$FileSystem.totalSize)
},
sizeLimit(): string {
return this.$filesize(this.$Config.personalFilesLimit)
},
sizeColor(): string {
return this.progress > 90 ? 'red' : 'green'
},
},
watch: {
totalSize() {
this.progress = this.$FileSystem.percentStorageUsed
},
},
})
</script>
<style scoped lang="less" src="./Aside.less"></style>
13 changes: 12 additions & 1 deletion components/views/files/controls/Controls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,19 @@ export default Vue.extend({
async handleFile(event: any) {
this.errors = []
this.$store.commit('ui/setIsLoadingFileIndex', true)

const originalFiles: File[] = [...event.target.files]

// if these files go over the storage limit, prevent upload
if (
originalFiles.reduce(
(total, curr) => total + curr.size,
this.$FileSystem.totalSize,
) > this.$Config.personalFilesLimit
) {
this.$store.commit('ui/setIsLoadingFileIndex', false)
this.errors.push(this.$t('pages.files.errors.limit') as string)
return
}
// todo - for now, index is stored in the bucket. we could try moving it to the thread, then sat.json wouldn't be reserved
const protectedNameResults: File[] = originalFiles.filter(
(file) => !(file.name === 'sat.json'),
Expand Down
7 changes: 6 additions & 1 deletion config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export const Config = {
routingMiddleware: {
prerequisitesCheckBypass: ['auth', 'setup'],
},
uploadByteLimit: 1048576 * 8, // 8mb
uploadByteLimit: 1000000 * 8, // 8MB - the current limit for an nsfw scan. Should be fixed in AP-807
personalFilesLimit: 1000000000 * 4, // 4GB - free tier limit
regex: {
// Regex to identify if a filetype is an image we support
image: '^.*.(apng|avif|gif|jpg|jpeg|jfif|pjpeg|pjp|png|svg|webp)$',
Expand Down Expand Up @@ -139,4 +140,8 @@ export const Config = {
size: { width: 600, height: 600 },
format: 'jpeg',
},
locale:
navigator.languages && navigator.languages.length
? navigator.languages[0]
: navigator.language,
}
23 changes: 23 additions & 0 deletions libraries/Files/FilSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ExportDirectory,
} from './types/filesystem'
import { FILE_TYPE } from './types/file'
import { Config } from '~/config'

export class FilSystem {
private _self = new Directory({ name: 'root' })
Expand Down Expand Up @@ -116,6 +117,28 @@ export class FilSystem {
return flatDeepByKey(this.export.content, 'children')
}

/**
* @method totalSize
* @returns {number} total size of all tracked files
*/
get totalSize(): number {
return this.flat.reduce(
(total, curr) =>
(Object.values(FILE_TYPE) as string[]).includes(curr.type)
? total + (curr as ExportFile).size
: total,
0,
)
}

/**
* @method percentStorageUsed
* @returns {number} percentage of available storage used
*/
get percentStorageUsed(): number {
return (this.totalSize / Config.personalFilesLimit) * 100
}

/**
* @method exportChildren
* @param {Item} item
Expand Down
1 change: 1 addition & 0 deletions locales/en-US.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export default {
reserved_name: 'sat.json is a reserved file name',
empty_file: 'File needs to have a size of 1 byte or greater',
file_name: 'File with name already exists in this file system',
limit: 'This upload would exceed your storage limit',
},
},
unlock: {
Expand Down
6 changes: 3 additions & 3 deletions plugins/thirdparty/filesize.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Vue from 'vue'

import fileSize from 'filesize'
import { filesize } from '~/utilities/Filesize'

declare module '@nuxt/types' {
interface Context {
$filesize: typeof fileSize
$filesize: typeof Function
}
}

Vue.prototype.$filesize = fileSize
Vue.prototype.$filesize = filesize
8 changes: 8 additions & 0 deletions utilities/Filesize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import fileSize from 'filesize'
import { Config } from '~/config'

export function filesize(bytes: number) {
return fileSize(bytes, {
locale: Config.locale,
})
}