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(files): blur nsfw image thumbnails based on settings #2958

Merged
merged 6 commits into from
Apr 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions assets/styles/framework/blurs.less
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@
.blur-more {
backdrop-filter: @heavy-blur;
}

.blur-image {
filter: @blur;
}
22 changes: 8 additions & 14 deletions components/views/files/controls/Controls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export default Vue.extend({
const sameNameResults: File[] = emptyFileResults.filter((file) => {
return !this.$FileSystem.currentDirectory.hasChild(file.name)
})
const nsfwResults: Promise<{ file: File; nsfw: boolean }>[] =
const files: Promise<{ file: File; nsfw: boolean }>[] =
sameNameResults.map(async (file: File) => {
// convert heic to jpg for scan. return original heic if sfw
if (await isHeic(file)) {
Expand All @@ -140,20 +140,17 @@ export default Vue.extend({
return { file, nsfw }
})

const files: File[] = []

for await (const el of nsfwResults) {
if (!el.nsfw) {
files.push(el.file)
}
}
for (const file of files) {
for await (const file of files) {
try {
this.$store.commit(
'ui/setFilesUploadStatus',
this.$t('pages.files.controls.upload', [file.name]),
this.$t('pages.files.controls.upload', [file.file.name]),
)
await this.$FileSystem.uploadFile(
file.file,
file.nsfw,
this.setProgress,
)
await this.$FileSystem.uploadFile(file, this.setProgress)
} catch (e: any) {
this.errors.push(e?.message ?? '')
}
Expand Down Expand Up @@ -183,9 +180,6 @@ export default Vue.extend({
if (emptyFileResults.length !== sameNameResults.length) {
this.errors.push(this.$t('pages.files.errors.duplicate_name'))
}
if (nsfwResults.length !== files.length) {
this.errors.push(this.$t('errors.chat.contains_nsfw'))
}
},
/**
* @method setProgress
Expand Down
9 changes: 8 additions & 1 deletion components/views/files/file/File.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@
@mouseleave="heartHover=false"
/>
</div>
<img v-if="item.thumbnail" class="image-preview" :src="item.thumbnail" />
<!-- add container so blur effect doesn't go outside the dimensions of the image -->
<div v-if="item.thumbnail" class="image-container">
<img
class="image-preview"
:class="{'blur-image' : item.nsfw && blockNsfw}"
:src="item.thumbnail"
/>
</div>
<div v-else class="icon-container">
<folder-icon v-if="item.content" size="4x" class="file-type-icon" />
<archive-icon v-else-if="isArchive" size="4x" class="file-type-icon" />
Expand Down
9 changes: 7 additions & 2 deletions components/views/files/file/File.less
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@
}
}

.image-preview {
.image-container {
overflow: hidden;
height: 162px;
object-fit: cover;
filter: brightness(0.75);
.image-preview {
height: 162px;
width: @full;
object-fit: cover;
}
}

.text-container {
Expand Down
6 changes: 5 additions & 1 deletion components/views/files/file/File.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Directory } from '~/libraries/Files/Directory'
import { Fil } from '~/libraries/Files/Fil'
import { ContextMenuItem, ModalWindows } from '~/store/ui/types'
import { isMimeArchive } from '~/utilities/FileType'
import { RootState } from '~/types/store/store'

export default Vue.extend({
components: {
Expand Down Expand Up @@ -47,7 +48,10 @@ export default Vue.extend({
}
},
computed: {
...mapState(['ui']),
...mapState({
ui: (state) => (state as RootState).ui,
blockNsfw: (state) => (state as RootState).settings.blockNsfw,
}),
/**
* @returns {string} if directory, child count. if file, size
*/
Expand Down
7 changes: 6 additions & 1 deletion components/views/files/view/View.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@
</div>
</div>
</div>
<img v-if="file.thumbnail" class="file-image" :src="file.thumbnail" />
<div v-if="file.thumbnail" class="image-container">
<img
:src="file.thumbnail"
:class="{'blur-image' : file.nsfw && blockNsfw}"
/>
</div>
<div v-else class="no-preview">
<UiLoadersSpinner v-if="isDownloading" class="file-icon" spinning />
<a
Expand Down
57 changes: 23 additions & 34 deletions components/views/files/view/View.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,6 @@
z-index: @base-z-index + 35;
padding: @normal-spacing;

.file-image {
display: flex;
margin: auto;
max-width: 80vw;
max-height: 60vh;
&:extend(.round-corners);
}
.file-icon {
font-size: 50pt;
margin: auto;
margin-bottom: @normal-spacing;
}
.no-preview {
display: flex;
flex-direction: column;
text-align: center;
margin: auto;
.subtitle {
display: block;
text-align: center;
margin-bottom: 0;
}
}
.progress {
display: flex;
margin: auto;
max-width: 1000px;
}

.file-nav {
width: calc(@full - @xlarge-spacing); //to account for margin
display: flex;
Expand Down Expand Up @@ -64,12 +35,30 @@
}
}
}
}

@media only screen and (min-width: calc(@mobile-breakpoint + 1px)) {
.swiper-slide-active {
#view-file {
transform: translate3d(calc(@sidebar-size + @servers-size), 0px, 0px);
.image-container {
display: flex;
margin: auto;
max-width: 80vw;
max-height: 60vh;
&:extend(.round-corners);
overflow: hidden;
}

.no-preview {
display: flex;
flex-direction: column;
text-align: center;
margin: auto;
.subtitle {
display: block;
text-align: center;
margin-bottom: 0;
}
.file-icon {
font-size: 50pt;
margin: auto;
margin-bottom: @normal-spacing;
}
}
}
6 changes: 5 additions & 1 deletion components/views/files/view/View.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
LinkIcon,
} from 'satellite-lucide-icons'
import { Fil } from '~/libraries/Files/Fil'
import { RootState } from '~/types/store/store'

export default Vue.extend({
components: {
Expand All @@ -27,7 +28,10 @@ export default Vue.extend({
}
},
computed: {
...mapState(['ui']),
...mapState({
ui: (state) => (state as RootState).ui,
blockNsfw: (state) => (state as RootState).settings.blockNsfw,
}),
isDownloading(): boolean {
return this.ui.fileDownloadList.includes(this.file?.name)
},
Expand Down
13 changes: 13 additions & 0 deletions libraries/Files/Fil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class Fil extends Item {
private _size: number = 0
private _thumbnail: string
private _extension: string
private _nsfw: boolean

/**
* @constructor
Expand All @@ -25,6 +26,7 @@ export class Fil extends Item {
type,
thumbnail,
extension,
nsfw,
}: {
id?: string
name: string
Expand All @@ -36,6 +38,7 @@ export class Fil extends Item {
type?: FILE_TYPE
thumbnail?: string
extension?: string
nsfw: boolean
}) {
if (!size) {
throw new Error(FileSystemErrors.FILE_SIZE)
Expand All @@ -48,6 +51,7 @@ export class Fil extends Item {
this._extension =
extension ||
name.slice(((name.lastIndexOf('.') - 1) >>> 0) + 2).toLowerCase()
this._nsfw = nsfw
}

/**
Expand All @@ -73,6 +77,7 @@ export class Fil extends Item {
type: this.type as FILE_TYPE,
thumbnail: this.thumbnail,
extension: this.extension,
nsfw: this._nsfw,
})
}

Expand Down Expand Up @@ -108,6 +113,14 @@ export class Fil extends Item {
return this._extension
}

/**
* @getter nsfw
* @returns nsfw status of file
*/
get nsfw(): boolean {
return this._nsfw
}

/**
* @setter file description text
* @param {string} content the content to set the file description to
Expand Down
7 changes: 7 additions & 0 deletions libraries/Files/FilSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export class FilSystem {
modified,
thumbnail,
extension,
nsfw,
} = item
return {
id,
Expand All @@ -170,6 +171,7 @@ export class FilSystem {
modified,
thumbnail,
extension,
nsfw,
}
}
const { id, name, liked, shared, type, modified } = item
Expand Down Expand Up @@ -216,6 +218,7 @@ export class FilSystem {
modified,
thumbnail,
extension,
nsfw,
} = item as ExportFile
const type = item.type as FILE_TYPE
this.createFile({
Expand All @@ -229,6 +232,7 @@ export class FilSystem {
modified,
thumbnail,
extension,
nsfw,
})
}
if ((Object.values(DIRECTORY_TYPE) as string[]).includes(item.type)) {
Expand Down Expand Up @@ -260,6 +264,7 @@ export class FilSystem {
modified,
thumbnail,
extension,
nsfw,
}: {
id?: string
name: string
Expand All @@ -271,6 +276,7 @@ export class FilSystem {
modified?: number
thumbnail?: string
extension?: string
nsfw: boolean
}): Fil | null {
const newFile = new Fil({
id,
Expand All @@ -283,6 +289,7 @@ export class FilSystem {
modified,
thumbnail,
extension,
nsfw,
})
const inserted = this.addChild(newFile)
return inserted ? newFile : null
Expand Down
3 changes: 2 additions & 1 deletion libraries/Files/TextileFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class TextileFileSystem extends FilSystem {
* @param {File} file file to be uploaded
* @param {Function} progressCallback used to show progress meter in componment that calls this method
*/
async uploadFile(file: File, progressCallback: Function) {
async uploadFile(file: File, nsfw: boolean, progressCallback: Function) {
const id = uuidv4()
await this.bucket.pushFile(file, id, progressCallback)
// read magic byte type, use metadata as backup
Expand All @@ -39,6 +39,7 @@ export class TextileFileSystem extends FilSystem {
size: file.size,
type: Object.values(FILE_TYPE).includes(type) ? type : FILE_TYPE.GENERIC,
thumbnail: await this._createThumbnail(file, byteType),
nsfw,
})
}

Expand Down
Loading