diff --git a/api/graphql/generated.go b/api/graphql/generated.go
index e4cb6341..902ea537 100644
--- a/api/graphql/generated.go
+++ b/api/graphql/generated.go
@@ -114,19 +114,20 @@ type ComplexityRoot struct {
}
Mutation struct {
- AuthorizeUser func(childComplexity int, username string, password string) int
- CreateUser func(childComplexity int, username string, rootPath string, password *string, admin bool) int
- DeleteShareToken func(childComplexity int, token string) int
- DeleteUser func(childComplexity int, id int) int
- FavoriteMedia func(childComplexity int, mediaID int, favorite bool) int
- InitialSetupWizard func(childComplexity int, username string, password string, rootPath string) int
- ProtectShareToken func(childComplexity int, token string, password *string) int
- RegisterUser func(childComplexity int, username string, password string, rootPath string) int
- ScanAll func(childComplexity int) int
- ScanUser func(childComplexity int, userID int) int
- ShareAlbum func(childComplexity int, albumID int, expire *time.Time, password *string) int
- ShareMedia func(childComplexity int, mediaID int, expire *time.Time, password *string) int
- UpdateUser func(childComplexity int, id int, username *string, rootPath *string, password *string, admin *bool) int
+ AuthorizeUser func(childComplexity int, username string, password string) int
+ CreateUser func(childComplexity int, username string, rootPath string, password *string, admin bool) int
+ DeleteShareToken func(childComplexity int, token string) int
+ DeleteUser func(childComplexity int, id int) int
+ FavoriteMedia func(childComplexity int, mediaID int, favorite bool) int
+ InitialSetupWizard func(childComplexity int, username string, password string, rootPath string) int
+ ProtectShareToken func(childComplexity int, token string, password *string) int
+ RegisterUser func(childComplexity int, username string, password string, rootPath string) int
+ ScanAll func(childComplexity int) int
+ ScanUser func(childComplexity int, userID int) int
+ SetPeriodicScanInterval func(childComplexity int, interval int) int
+ ShareAlbum func(childComplexity int, albumID int, expire *time.Time, password *string) int
+ ShareMedia func(childComplexity int, mediaID int, expire *time.Time, password *string) int
+ UpdateUser func(childComplexity int, id int, username *string, rootPath *string, password *string, admin *bool) int
}
Notification struct {
@@ -241,6 +242,7 @@ type MutationResolver interface {
UpdateUser(ctx context.Context, id int, username *string, rootPath *string, password *string, admin *bool) (*models.User, error)
CreateUser(ctx context.Context, username string, rootPath string, password *string, admin bool) (*models.User, error)
DeleteUser(ctx context.Context, id int) (*models.User, error)
+ SetPeriodicScanInterval(ctx context.Context, interval int) (int, error)
}
type QueryResolver interface {
SiteInfo(ctx context.Context) (*models.SiteInfo, error)
@@ -713,6 +715,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.ScanUser(childComplexity, args["userId"].(int)), true
+ case "Mutation.setPeriodicScanInterval":
+ if e.complexity.Mutation.SetPeriodicScanInterval == nil {
+ break
+ }
+
+ args, err := ec.field_Mutation_setPeriodicScanInterval_args(context.TODO(), rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Mutation.SetPeriodicScanInterval(childComplexity, args["interval"].(int)), true
+
case "Mutation.shareAlbum":
if e.complexity.Mutation.ShareAlbum == nil {
break
@@ -1307,6 +1321,12 @@ type Mutation {
admin: Boolean!
): User @isAdmin
deleteUser(id: Int!): User @isAdmin
+
+ """
+ Set how often, in seconds, the server should automatically scan for new media,
+ a value of 0 will disable periodic scans
+ """
+ setPeriodicScanInterval(interval: Int!): Int!
}
type Subscription {
@@ -1748,6 +1768,21 @@ func (ec *executionContext) field_Mutation_scanUser_args(ctx context.Context, ra
return args, nil
}
+func (ec *executionContext) field_Mutation_setPeriodicScanInterval_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
+ var err error
+ args := map[string]interface{}{}
+ var arg0 int
+ if tmp, ok := rawArgs["interval"]; ok {
+ ctx := graphql.WithFieldInputContext(ctx, graphql.NewFieldInputWithField("interval"))
+ arg0, err = ec.unmarshalNInt2int(ctx, tmp)
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["interval"] = arg0
+ return args, nil
+}
+
func (ec *executionContext) field_Mutation_shareAlbum_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
@@ -4127,6 +4162,47 @@ func (ec *executionContext) _Mutation_deleteUser(ctx context.Context, field grap
return ec.marshalOUser2ᚖgithubᚗcomᚋviktorstrateᚋphotoviewᚋapiᚋgraphqlᚋmodelsᚐUser(ctx, field.Selections, res)
}
+func (ec *executionContext) _Mutation_setPeriodicScanInterval(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ ret = graphql.Null
+ }
+ }()
+ fc := &graphql.FieldContext{
+ Object: "Mutation",
+ Field: field,
+ Args: nil,
+ IsMethod: true,
+ }
+
+ ctx = graphql.WithFieldContext(ctx, fc)
+ rawArgs := field.ArgumentMap(ec.Variables)
+ args, err := ec.field_Mutation_setPeriodicScanInterval_args(ctx, rawArgs)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ fc.Args = args
+ resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().SetPeriodicScanInterval(rctx, args["interval"].(int))
+ })
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if resTmp == nil {
+ if !graphql.HasFieldError(ctx, fc) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(int)
+ fc.Result = res
+ return ec.marshalNInt2int(ctx, field.Selections, res)
+}
+
func (ec *executionContext) _Notification_key(ctx context.Context, field graphql.CollectedField, obj *models.Notification) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@@ -7545,6 +7621,11 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
out.Values[i] = ec._Mutation_createUser(ctx, field)
case "deleteUser":
out.Values[i] = ec._Mutation_deleteUser(ctx, field)
+ case "setPeriodicScanInterval":
+ out.Values[i] = ec._Mutation_setPeriodicScanInterval(ctx, field)
+ if out.Values[i] == graphql.Null {
+ invalids++
+ }
default:
panic("unknown field " + strconv.Quote(field.Name))
}
diff --git a/api/graphql/resolvers/scanner.go b/api/graphql/resolvers/scanner.go
index e57105e1..ee905ece 100644
--- a/api/graphql/resolvers/scanner.go
+++ b/api/graphql/resolvers/scanner.go
@@ -39,3 +39,23 @@ func (r *mutationResolver) ScanUser(ctx context.Context, userID int) (*models.Sc
Message: &startMessage,
}, nil
}
+
+func (r *mutationResolver) SetPeriodicScanInterval(ctx context.Context, interval int) (int, error) {
+ if interval < 0 {
+ return 0, errors.New("interval must be 0 or above")
+ }
+
+ _, err := r.Database.Exec("UPDATE site_info SET periodic_scan_interval = ?", interval)
+ if err != nil {
+ return 0, err
+ }
+
+ var dbInterval int
+
+ row := r.Database.QueryRow("SELECT periodic_scan_interval FROM site_info")
+ if err = row.Scan(&dbInterval); err != nil {
+ return 0, err
+ }
+
+ return dbInterval, nil
+}
diff --git a/api/graphql/schema.graphql b/api/graphql/schema.graphql
index b343efa8..d3932e66 100644
--- a/api/graphql/schema.graphql
+++ b/api/graphql/schema.graphql
@@ -92,6 +92,12 @@ type Mutation {
admin: Boolean!
): User @isAdmin
deleteUser(id: Int!): User @isAdmin
+
+ """
+ Set how often, in seconds, the server should automatically scan for new media,
+ a value of 0 will disable periodic scans
+ """
+ setPeriodicScanInterval(interval: Int!): Int!
}
type Subscription {
diff --git a/ui/src/Pages/SettingsPage/ScannerSection.js b/ui/src/Pages/SettingsPage/ScannerSection.js
index 6b32bc01..834b731f 100644
--- a/ui/src/Pages/SettingsPage/ScannerSection.js
+++ b/ui/src/Pages/SettingsPage/ScannerSection.js
@@ -1,6 +1,13 @@
import React, { useState } from 'react'
-import { Button, Checkbox, Dropdown, Icon, Input } from 'semantic-ui-react'
+import {
+ Button,
+ Checkbox,
+ Dropdown,
+ Icon,
+ Input,
+ Loader,
+} from 'semantic-ui-react'
import { useMutation, useQuery } from 'react-apollo'
import gql from 'graphql-tag'
import styled from 'styled-components'
@@ -23,6 +30,12 @@ const SCAN_INTERVAL_QUERY = gql`
}
`
+const SCAN_INTERVAL_MUTATION = gql`
+ mutation changeScanIntervalMutation($interval: Int!) {
+ setPeriodicScanInterval(interval: $interval)
+ }
+`
+
const timeUnits = [
{
value: 'second',
@@ -46,6 +59,10 @@ const timeUnits = [
},
]
+const convertToSeconds = ({ value, unit }) => {
+ return parseInt(value * timeUnits.find(x => x.value == unit).multiplier)
+}
+
const convertToAppropriateUnit = ({ value, unit }) => {
if (value == 0) {
return {
@@ -54,7 +71,7 @@ const convertToAppropriateUnit = ({ value, unit }) => {
}
}
- const seconds = value * timeUnits.find(x => x.value == unit).multiplier
+ const seconds = convertToSeconds({ value, unit })
let resultingUnit = timeUnits.first
for (const unit of timeUnits) {
@@ -113,6 +130,29 @@ const ScannerSection = () => {
},
})
+ const [
+ setScanIntervalMutation,
+ { loading: scanIntervalMutationLoading },
+ ] = useMutation(SCAN_INTERVAL_MUTATION)
+
+ const onScanIntervalCheckboxChange = checked => {
+ setEnablePeriodicScanner(checked)
+
+ setScanIntervalMutation({
+ variables: {
+ interval: checked ? convertToSeconds(scanInterval) : 0,
+ },
+ })
+ }
+
+ const onScanIntervalUpdate = scanInterval => {
+ setScanIntervalMutation({
+ variables: {
+ interval: convertToSeconds(scanInterval),
+ },
+ })
+ }
+
const scanIntervalUnits = [
{
key: 'second',
@@ -163,7 +203,7 @@ const ScannerSection = () => {
label="Enable periodic scanner"
disabled={scanIntervalQuery.loading}
checked={enablePeriodicScanner}
- onChange={(_, { checked }) => setEnablePeriodicScanner(checked)}
+ onChange={(_, { checked }) => onScanIntervalCheckboxChange(checked)}
/>
@@ -178,25 +218,43 @@ const ScannerSection = () => {
- setScanInterval(x => ({
- ...x,
+ onChange={(_, { value }) => {
+ const newScanInterval = {
+ ...scanInterval,
unit: value,
- }))
- }
+ }
+
+ setScanInterval(newScanInterval)
+ onScanIntervalUpdate(newScanInterval)
+ }}
value={scanInterval.unit}
options={scanIntervalUnits}
/>
}
+ onBlur={() => onScanIntervalUpdate(scanInterval)}
+ onKeyDown={({ key }) =>
+ key == 'Enter' && onScanIntervalUpdate(scanInterval)
+ }
loading={scanIntervalQuery.loading}
labelPosition="right"
style={{ maxWidth: 300 }}
id="periodic_scan_field"
value={scanInterval.value}
- onChange={e => setScanInterval(e.target.value)}
+ onChange={(_, { value }) => {
+ setScanInterval(x => ({
+ ...x,
+ value,
+ }))
+ }}
/>
>
)}
+
)
}