2017-11-10 03:33:11 +00:00
package common
2017-01-01 15:45:43 +00:00
2017-05-29 14:52:37 +00:00
import (
2017-11-11 23:34:27 +00:00
"database/sql"
2017-09-03 04:50:31 +00:00
"encoding/json"
2017-08-13 11:22:34 +00:00
"errors"
2018-04-22 12:33:56 +00:00
"io"
2017-05-29 14:52:37 +00:00
"io/ioutil"
2017-09-03 04:50:31 +00:00
"log"
2017-05-29 14:52:37 +00:00
"net/http"
2017-09-03 04:50:31 +00:00
"os"
"reflect"
2017-09-10 16:57:22 +00:00
"sync"
"sync/atomic"
2017-11-11 04:06:16 +00:00
2018-10-27 03:21:02 +00:00
"github.com/Azareal/Gosora/query_gen"
2017-05-29 14:52:37 +00:00
)
2017-01-01 15:45:43 +00:00
2018-10-02 04:09:17 +00:00
// TODO: Something more thread-safe
2017-12-01 02:04:29 +00:00
type ThemeList map [ string ] * Theme
2017-11-06 04:02:35 +00:00
2018-05-27 09:36:35 +00:00
var Themes ThemeList = make ( map [ string ] * Theme ) // ? Refactor this into a store?
2017-11-10 03:33:11 +00:00
var DefaultThemeBox atomic . Value
2017-11-11 04:06:16 +00:00
var ChangeDefaultThemeMutex sync . Mutex
2017-01-01 15:45:43 +00:00
2018-12-08 00:45:27 +00:00
// TODO: Fallback to a random theme if this doesn't exist, so admins can remove themes they don't use
2017-09-22 02:21:17 +00:00
// TODO: Use this when the default theme doesn't exist
2018-03-17 08:16:43 +00:00
var fallbackTheme = "cosora"
2018-05-27 09:36:35 +00:00
var overridenTemplates = make ( map [ string ] bool ) // ? What is this used for?
2017-06-19 08:06:54 +00:00
2017-11-11 23:34:27 +00:00
type ThemeStmts struct {
2018-10-02 04:09:17 +00:00
getThemes * sql . Stmt
isThemeDefault * sql . Stmt
updateTheme * sql . Stmt
addTheme * sql . Stmt
2017-11-11 23:34:27 +00:00
}
var themeStmts ThemeStmts
2017-09-23 19:57:13 +00:00
func init ( ) {
2017-11-11 04:06:16 +00:00
DefaultThemeBox . Store ( fallbackTheme )
2017-11-12 03:29:05 +00:00
DbInits . Add ( func ( acc * qgen . Accumulator ) error {
2017-11-11 23:34:27 +00:00
themeStmts = ThemeStmts {
2018-10-02 04:09:17 +00:00
getThemes : acc . Select ( "themes" ) . Columns ( "uname, default" ) . Prepare ( ) ,
isThemeDefault : acc . Select ( "themes" ) . Columns ( "default" ) . Where ( "uname = ?" ) . Prepare ( ) ,
updateTheme : acc . Update ( "themes" ) . Set ( "default = ?" ) . Where ( "uname = ?" ) . Prepare ( ) ,
addTheme : acc . Insert ( "themes" ) . Columns ( "uname, default" ) . Fields ( "?,?" ) . Prepare ( ) ,
2017-11-11 23:34:27 +00:00
}
return acc . FirstError ( )
} )
2017-09-23 19:57:13 +00:00
}
2018-05-27 09:36:35 +00:00
func NewThemeList ( ) ( themes ThemeList , err error ) {
themes = make ( map [ string ] * Theme )
2018-03-11 09:33:49 +00:00
2017-01-01 15:45:43 +00:00
themeFiles , err := ioutil . ReadDir ( "./themes" )
if err != nil {
2018-05-27 09:36:35 +00:00
return themes , err
2017-01-01 15:45:43 +00:00
}
2017-05-29 14:52:37 +00:00
2017-01-01 15:45:43 +00:00
for _ , themeFile := range themeFiles {
if ! themeFile . IsDir ( ) {
continue
}
2017-05-29 14:52:37 +00:00
2017-01-01 15:45:43 +00:00
themeName := themeFile . Name ( )
2017-11-29 02:34:02 +00:00
log . Printf ( "Adding theme '%s'" , themeName )
2018-05-27 09:36:35 +00:00
themePath := "./themes/" + themeName
themeFile , err := ioutil . ReadFile ( themePath + "/theme.json" )
2017-01-01 15:45:43 +00:00
if err != nil {
2018-05-27 09:36:35 +00:00
return themes , err
2017-01-01 15:45:43 +00:00
}
2017-05-29 14:52:37 +00:00
2017-12-01 02:04:29 +00:00
var theme = & Theme { Name : "" }
err = json . Unmarshal ( themeFile , theme )
2017-01-07 06:31:04 +00:00
if err != nil {
2018-05-27 09:36:35 +00:00
return themes , err
}
// TODO: Implement the static file part of this and fsnotify
if theme . Path != "" {
log . Print ( "Resolving redirect to " + theme . Path )
themeFile , err := ioutil . ReadFile ( theme . Path + "/theme.json" )
if err != nil {
return themes , err
}
theme = & Theme { Name : "" , Path : theme . Path }
err = json . Unmarshal ( themeFile , theme )
if err != nil {
return themes , err
}
} else {
theme . Path = themePath
2017-01-07 06:31:04 +00:00
}
2017-05-29 14:52:37 +00:00
2017-01-01 15:45:43 +00:00
theme . Active = false // Set this to false, just in case someone explicitly overrode this value in the JSON file
2017-05-29 14:52:37 +00:00
Added Quick Topic.
Added Attachments.
Added Attachment Media Embeds.
Renamed a load of *Store and *Cache methods to reduce the amount of unneccesary typing.
Added petabytes as a unit and cleaned up a few of the friendly units.
Refactored the username change logic to make it easier to maintain.
Refactored the avatar change logic to make it easier to maintain.
Shadow now uses CSS Variables for most of it's colours. We have plans to transpile this to support older browsers later on!
Snuck some CSS Variables into Tempra Conflux.
Added the GroupCache interface to MemoryGroupStore.
Added the Length method to MemoryGroupStore.
Added support for a site short name.
Added the UploadFiles permission.
Renamed more functions.
Fixed the background for the left gutter on the postbit for Tempra Simple and Shadow.
Added support for if statements operating on int8, int16, int32, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64 for the template compiler.
Added support for if statements operating on slices and maps for the template compiler.
Fixed a security exploit in reply editing.
Fixed a bug in the URL detector in the parser where it couldn't find URLs with non-standard ports.
Fixed buttons having blue outlines on focus on Shadow.
Refactored the topic creation logic to make it easier to maintain.
Made a few responsive fixes, but there's still more to do in the following commits!
2017-10-05 10:20:28 +00:00
// TODO: Let the theme specify where it's resources are via the JSON file?
// TODO: Let the theme inherit CSS from another theme?
// ? - This might not be too helpful, as it only searches for /public/ and not if /public/ is empty. Still, it might help some people with a slightly less cryptic error
2018-05-27 09:36:35 +00:00
log . Print ( theme . Path + "/public/" )
_ , err = os . Stat ( theme . Path + "/public/" )
Added Quick Topic.
Added Attachments.
Added Attachment Media Embeds.
Renamed a load of *Store and *Cache methods to reduce the amount of unneccesary typing.
Added petabytes as a unit and cleaned up a few of the friendly units.
Refactored the username change logic to make it easier to maintain.
Refactored the avatar change logic to make it easier to maintain.
Shadow now uses CSS Variables for most of it's colours. We have plans to transpile this to support older browsers later on!
Snuck some CSS Variables into Tempra Conflux.
Added the GroupCache interface to MemoryGroupStore.
Added the Length method to MemoryGroupStore.
Added support for a site short name.
Added the UploadFiles permission.
Renamed more functions.
Fixed the background for the left gutter on the postbit for Tempra Simple and Shadow.
Added support for if statements operating on int8, int16, int32, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64 for the template compiler.
Added support for if statements operating on slices and maps for the template compiler.
Fixed a security exploit in reply editing.
Fixed a bug in the URL detector in the parser where it couldn't find URLs with non-standard ports.
Fixed buttons having blue outlines on focus on Shadow.
Refactored the topic creation logic to make it easier to maintain.
Made a few responsive fixes, but there's still more to do in the following commits!
2017-10-05 10:20:28 +00:00
if err != nil {
if os . IsNotExist ( err ) {
2018-05-27 09:36:35 +00:00
return themes , errors . New ( "We couldn't find this theme's resources. E.g. the /public/ folder." )
Added Quick Topic.
Added Attachments.
Added Attachment Media Embeds.
Renamed a load of *Store and *Cache methods to reduce the amount of unneccesary typing.
Added petabytes as a unit and cleaned up a few of the friendly units.
Refactored the username change logic to make it easier to maintain.
Refactored the avatar change logic to make it easier to maintain.
Shadow now uses CSS Variables for most of it's colours. We have plans to transpile this to support older browsers later on!
Snuck some CSS Variables into Tempra Conflux.
Added the GroupCache interface to MemoryGroupStore.
Added the Length method to MemoryGroupStore.
Added support for a site short name.
Added the UploadFiles permission.
Renamed more functions.
Fixed the background for the left gutter on the postbit for Tempra Simple and Shadow.
Added support for if statements operating on int8, int16, int32, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64 for the template compiler.
Added support for if statements operating on slices and maps for the template compiler.
Fixed a security exploit in reply editing.
Fixed a bug in the URL detector in the parser where it couldn't find URLs with non-standard ports.
Fixed buttons having blue outlines on focus on Shadow.
Refactored the topic creation logic to make it easier to maintain.
Made a few responsive fixes, but there's still more to do in the following commits!
2017-10-05 10:20:28 +00:00
} else {
log . Print ( "We weren't able to access this theme's resources due to a permissions issue or some other problem" )
2018-05-27 09:36:35 +00:00
return themes , err
Added Quick Topic.
Added Attachments.
Added Attachment Media Embeds.
Renamed a load of *Store and *Cache methods to reduce the amount of unneccesary typing.
Added petabytes as a unit and cleaned up a few of the friendly units.
Refactored the username change logic to make it easier to maintain.
Refactored the avatar change logic to make it easier to maintain.
Shadow now uses CSS Variables for most of it's colours. We have plans to transpile this to support older browsers later on!
Snuck some CSS Variables into Tempra Conflux.
Added the GroupCache interface to MemoryGroupStore.
Added the Length method to MemoryGroupStore.
Added support for a site short name.
Added the UploadFiles permission.
Renamed more functions.
Fixed the background for the left gutter on the postbit for Tempra Simple and Shadow.
Added support for if statements operating on int8, int16, int32, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64 for the template compiler.
Added support for if statements operating on slices and maps for the template compiler.
Fixed a security exploit in reply editing.
Fixed a bug in the URL detector in the parser where it couldn't find URLs with non-standard ports.
Fixed buttons having blue outlines on focus on Shadow.
Refactored the topic creation logic to make it easier to maintain.
Made a few responsive fixes, but there's still more to do in the following commits!
2017-10-05 10:20:28 +00:00
}
}
2017-01-07 06:31:04 +00:00
if theme . FullImage != "" {
2018-02-19 04:26:01 +00:00
DebugLog ( "Adding theme image" )
2018-05-27 09:36:35 +00:00
err = StaticFiles . Add ( theme . Path + "/" + theme . FullImage , themePath )
2017-01-07 06:31:04 +00:00
if err != nil {
2018-05-27 09:36:35 +00:00
return themes , err
2017-01-07 06:31:04 +00:00
}
}
2017-05-29 14:52:37 +00:00
2017-09-23 19:57:13 +00:00
theme . TemplatesMap = make ( map [ string ] string )
theme . TmplPtr = make ( map [ string ] interface { } )
if theme . Templates != nil {
for _ , themeTmpl := range theme . Templates {
theme . TemplatesMap [ themeTmpl . Name ] = themeTmpl . Source
2017-11-11 04:06:16 +00:00
theme . TmplPtr [ themeTmpl . Name ] = TmplPtrMap [ "o_" + themeTmpl . Source ]
2017-09-23 19:57:13 +00:00
}
}
2018-05-27 09:36:35 +00:00
// TODO: Bind the built template, or an interpreted one for any dock overrides this theme has
themes [ theme . Name ] = theme
2017-01-01 15:45:43 +00:00
}
2018-05-27 09:36:35 +00:00
return themes , nil
2017-01-01 15:45:43 +00:00
}
2018-05-27 09:36:35 +00:00
// TODO: Make the initThemes and LoadThemes functions less confusing
// ? - Delete themes which no longer exist in the themes folder from the database?
func ( themes ThemeList ) LoadActiveStatus ( ) error {
ChangeDefaultThemeMutex . Lock ( )
2018-10-02 04:09:17 +00:00
defer ChangeDefaultThemeMutex . Unlock ( )
2018-05-27 09:36:35 +00:00
rows , err := themeStmts . getThemes . Query ( )
if err != nil {
return err
}
defer rows . Close ( )
2017-12-01 02:04:29 +00:00
2018-05-27 09:36:35 +00:00
var uname string
var defaultThemeSwitch bool
for rows . Next ( ) {
err = rows . Scan ( & uname , & defaultThemeSwitch )
2017-01-01 15:45:43 +00:00
if err != nil {
return err
}
2017-05-29 14:52:37 +00:00
2018-05-27 09:36:35 +00:00
// Was the theme deleted at some point?
theme , ok := themes [ uname ]
if ! ok {
continue
2017-01-01 15:45:43 +00:00
}
2017-05-29 14:52:37 +00:00
2018-05-27 09:36:35 +00:00
if defaultThemeSwitch {
2018-10-02 04:09:17 +00:00
DebugLogf ( "Loading the default theme '%s'" , theme . Name )
2018-05-27 09:36:35 +00:00
theme . Active = true
DefaultThemeBox . Store ( theme . Name )
theme . MapTemplates ( )
} else {
2018-10-02 04:09:17 +00:00
DebugLogf ( "Loading the theme '%s'" , theme . Name )
2018-05-27 09:36:35 +00:00
theme . Active = false
2017-05-07 08:31:41 +00:00
}
2017-06-25 09:56:39 +00:00
2018-05-27 09:36:35 +00:00
themes [ uname ] = theme
}
return rows . Err ( )
2017-01-01 15:45:43 +00:00
}
2018-05-27 09:36:35 +00:00
func ( themes ThemeList ) LoadStaticFiles ( ) error {
for _ , theme := range themes {
err := theme . LoadStaticFiles ( )
if err != nil {
return err
2017-01-01 15:45:43 +00:00
}
}
2018-05-27 09:36:35 +00:00
return nil
2017-01-01 15:45:43 +00:00
}
2017-11-11 04:06:16 +00:00
func ResetTemplateOverrides ( ) {
2017-01-01 15:45:43 +00:00
log . Print ( "Resetting the template overrides" )
2017-09-03 04:50:31 +00:00
for name := range overridenTemplates {
2017-01-01 15:45:43 +00:00
log . Print ( "Resetting '" + name + "' template override" )
2017-05-29 14:52:37 +00:00
2017-11-11 04:06:16 +00:00
originPointer , ok := TmplPtrMap [ "o_" + name ]
2017-01-01 15:45:43 +00:00
if ! ok {
log . Print ( "The origin template doesn't exist!" )
return
}
2017-05-29 14:52:37 +00:00
2017-11-11 04:06:16 +00:00
destTmplPtr , ok := TmplPtrMap [ name ]
2017-01-01 15:45:43 +00:00
if ! ok {
log . Print ( "The destination template doesn't exist!" )
return
}
2017-05-29 14:52:37 +00:00
2017-01-01 16:14:38 +00:00
// Not really a pointer, more of a function handle, an artifact from one of the earlier versions of themes.go
2017-09-03 04:50:31 +00:00
switch oPtr := originPointer . ( type ) {
2018-06-06 00:21:22 +00:00
case func ( CustomPagePage , io . Writer ) error :
switch dPtr := destTmplPtr . ( type ) {
case * func ( CustomPagePage , io . Writer ) error :
* dPtr = oPtr
default :
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
}
2018-04-22 12:33:56 +00:00
case func ( TopicPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( TopicPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
2017-01-01 15:45:43 +00:00
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
2018-04-22 12:33:56 +00:00
case func ( TopicListPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( TopicListPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
2018-04-22 12:33:56 +00:00
case func ( ForumPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( ForumPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
2018-04-22 12:33:56 +00:00
case func ( ForumsPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( ForumsPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
2018-04-22 12:33:56 +00:00
case func ( ProfilePage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( ProfilePage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
2018-04-22 12:33:56 +00:00
case func ( CreateTopicPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( CreateTopicPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
2018-04-22 12:33:56 +00:00
case func ( IPSearchPage , io . Writer ) error :
2018-03-08 03:59:47 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( IPSearchPage , io . Writer ) error :
2018-03-08 03:59:47 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2018-03-08 03:59:47 +00:00
}
2018-06-17 07:28:18 +00:00
case func ( AccountDashPage , io . Writer ) error :
switch dPtr := destTmplPtr . ( type ) {
case * func ( AccountDashPage , io . Writer ) error :
* dPtr = oPtr
default :
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
}
2018-06-06 00:21:22 +00:00
case func ( ErrorPage , io . Writer ) error :
switch dPtr := destTmplPtr . ( type ) {
case * func ( ErrorPage , io . Writer ) error :
* dPtr = oPtr
default :
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
}
2018-04-22 12:33:56 +00:00
case func ( Page , io . Writer ) error :
2017-09-03 04:50:31 +00:00
switch dPtr := destTmplPtr . ( type ) {
2018-04-22 12:33:56 +00:00
case * func ( Page , io . Writer ) error :
2017-09-03 04:50:31 +00:00
* dPtr = oPtr
default :
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "The source and destination templates are incompatible" ) )
2017-09-03 04:50:31 +00:00
}
default :
2018-03-17 08:16:43 +00:00
log . Print ( "name: " , name )
2018-03-11 09:33:49 +00:00
LogError ( errors . New ( "Unknown destination template type!" ) )
2017-01-01 15:45:43 +00:00
}
log . Print ( "The template override was reset" )
}
2017-09-03 04:50:31 +00:00
overridenTemplates = make ( map [ string ] bool )
2017-01-01 15:45:43 +00:00
log . Print ( "All of the template overrides have been reset" )
}
2017-08-13 11:22:34 +00:00
2018-11-17 02:36:02 +00:00
type GzipResponseWriter struct {
io . Writer
http . ResponseWriter
}
func ( w GzipResponseWriter ) Write ( b [ ] byte ) ( int , error ) {
return w . Writer . Write ( b )
}
2017-08-13 11:22:34 +00:00
// NEW method of doing theme templates to allow one user to have a different theme to another. Under construction.
2017-09-10 16:57:22 +00:00
// TODO: Generate the type switch instead of writing it by hand
// TODO: Cut the number of types in half
2018-12-08 00:45:27 +00:00
func ( theme * Theme ) RunTmpl ( template string , pi interface { } , w io . Writer ) error {
2018-11-17 02:36:02 +00:00
// Unpack this to avoid an indirect call
gzw , ok := w . ( GzipResponseWriter )
if ok {
w = gzw . Writer
}
2018-12-08 00:45:27 +00:00
var getTmpl = theme . GetTmpl ( template )
2017-10-30 09:57:08 +00:00
switch tmplO := getTmpl . ( type ) {
2018-06-06 00:21:22 +00:00
case * func ( CustomPagePage , io . Writer ) error :
var tmpl = * tmplO
return tmpl ( pi . ( CustomPagePage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( TopicPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2017-10-30 09:57:08 +00:00
return tmpl ( pi . ( TopicPage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( TopicListPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2018-04-22 12:33:56 +00:00
return tmpl ( pi . ( TopicListPage ) , w )
case * func ( ForumPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2017-10-30 09:57:08 +00:00
return tmpl ( pi . ( ForumPage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( ForumsPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2017-10-30 09:57:08 +00:00
return tmpl ( pi . ( ForumsPage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( ProfilePage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2017-10-30 09:57:08 +00:00
return tmpl ( pi . ( ProfilePage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( CreateTopicPage , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2017-10-30 09:57:08 +00:00
return tmpl ( pi . ( CreateTopicPage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( IPSearchPage , io . Writer ) error :
2018-03-08 03:59:47 +00:00
var tmpl = * tmplO
return tmpl ( pi . ( IPSearchPage ) , w )
2018-06-17 07:28:18 +00:00
case * func ( AccountDashPage , io . Writer ) error :
var tmpl = * tmplO
return tmpl ( pi . ( AccountDashPage ) , w )
2018-06-06 00:21:22 +00:00
case * func ( ErrorPage , io . Writer ) error :
var tmpl = * tmplO
return tmpl ( pi . ( ErrorPage ) , w )
2018-04-22 12:33:56 +00:00
case * func ( Page , io . Writer ) error :
2017-09-03 04:50:31 +00:00
var tmpl = * tmplO
2017-10-30 09:57:08 +00:00
return tmpl ( pi . ( Page ) , w )
2018-06-06 00:21:22 +00:00
case func ( CustomPagePage , io . Writer ) error :
return tmplO ( pi . ( CustomPagePage ) , w )
2018-04-22 12:33:56 +00:00
case func ( TopicPage , io . Writer ) error :
2017-10-30 09:57:08 +00:00
return tmplO ( pi . ( TopicPage ) , w )
2018-04-22 12:33:56 +00:00
case func ( TopicListPage , io . Writer ) error :
return tmplO ( pi . ( TopicListPage ) , w )
case func ( ForumPage , io . Writer ) error :
2017-10-30 09:57:08 +00:00
return tmplO ( pi . ( ForumPage ) , w )
2018-04-22 12:33:56 +00:00
case func ( ForumsPage , io . Writer ) error :
2017-10-30 09:57:08 +00:00
return tmplO ( pi . ( ForumsPage ) , w )
2018-04-22 12:33:56 +00:00
case func ( ProfilePage , io . Writer ) error :
2017-10-30 09:57:08 +00:00
return tmplO ( pi . ( ProfilePage ) , w )
2018-04-22 12:33:56 +00:00
case func ( CreateTopicPage , io . Writer ) error :
2017-10-30 09:57:08 +00:00
return tmplO ( pi . ( CreateTopicPage ) , w )
2018-04-22 12:33:56 +00:00
case func ( IPSearchPage , io . Writer ) error :
2018-03-08 03:59:47 +00:00
return tmplO ( pi . ( IPSearchPage ) , w )
2018-06-17 07:28:18 +00:00
case func ( AccountDashPage , io . Writer ) error :
return tmplO ( pi . ( AccountDashPage ) , w )
2018-06-06 00:21:22 +00:00
case func ( ErrorPage , io . Writer ) error :
return tmplO ( pi . ( ErrorPage ) , w )
2018-04-22 12:33:56 +00:00
case func ( Page , io . Writer ) error :
2017-10-30 09:57:08 +00:00
return tmplO ( pi . ( Page ) , w )
2018-06-24 13:49:29 +00:00
case nil , string :
2018-12-08 00:45:27 +00:00
mapping , ok := theme . TemplatesMap [ template ]
2017-09-03 04:50:31 +00:00
if ! ok {
mapping = template
}
2017-11-11 04:06:16 +00:00
return Templates . ExecuteTemplate ( w , mapping + ".html" , pi )
2017-09-03 04:50:31 +00:00
default :
log . Print ( "theme " , theme )
log . Print ( "template " , template )
log . Print ( "pi " , pi )
log . Print ( "tmplO " , tmplO )
2017-10-30 09:57:08 +00:00
log . Print ( "getTmpl " , getTmpl )
2017-09-03 04:50:31 +00:00
valueOf := reflect . ValueOf ( tmplO )
log . Print ( "initial valueOf.Type()" , valueOf . Type ( ) )
for valueOf . Kind ( ) == reflect . Interface || valueOf . Kind ( ) == reflect . Ptr {
valueOf = valueOf . Elem ( )
log . Print ( "valueOf.Elem().Type() " , valueOf . Type ( ) )
}
log . Print ( "deferenced valueOf.Type() " , valueOf . Type ( ) )
log . Print ( "valueOf.Kind() " , valueOf . Kind ( ) )
2017-10-30 09:57:08 +00:00
return errors . New ( "Unknown template type" )
2017-08-13 11:22:34 +00:00
}
}
2017-09-03 04:50:31 +00:00
// GetThemeTemplate attempts to get the template for a specific theme, otherwise it falls back on the default template pointer, which if absent will fallback onto the template interpreter
2018-12-08 00:45:27 +00:00
func ( theme * Theme ) GetTmpl ( template string ) interface { } {
2018-06-24 13:49:29 +00:00
// TODO: Figure out why we're getting a nil pointer here when transpiled templates are disabled, I would have assumed that we would just fall back to !ok on this
// Might have something to do with it being the theme's TmplPtr map, investigate.
2018-12-08 00:45:27 +00:00
tmpl , ok := theme . TmplPtr [ template ]
2017-09-03 04:50:31 +00:00
if ok {
2017-08-13 11:22:34 +00:00
return tmpl
}
2017-11-11 04:06:16 +00:00
tmpl , ok = TmplPtrMap [ template ]
2017-09-03 04:50:31 +00:00
if ok {
return tmpl
}
return template
2017-08-13 11:22:34 +00:00
}
2017-09-03 04:50:31 +00:00
// CreateThemeTemplate creates a theme template on the current default theme
2017-08-13 11:22:34 +00:00
func CreateThemeTemplate ( theme string , name string ) {
2017-11-11 04:06:16 +00:00
Themes [ theme ] . TmplPtr [ name ] = func ( pi Page , w http . ResponseWriter ) error {
mapping , ok := Themes [ DefaultThemeBox . Load ( ) . ( string ) ] . TemplatesMap [ name ]
2017-08-13 11:22:34 +00:00
if ! ok {
mapping = name
}
2017-11-11 04:06:16 +00:00
return Templates . ExecuteTemplate ( w , mapping + ".html" , pi )
2017-08-13 11:22:34 +00:00
}
}
2017-09-10 16:57:22 +00:00
func GetDefaultThemeName ( ) string {
2017-11-11 04:06:16 +00:00
return DefaultThemeBox . Load ( ) . ( string )
2017-09-10 16:57:22 +00:00
}
func SetDefaultThemeName ( name string ) {
2017-11-11 04:06:16 +00:00
DefaultThemeBox . Store ( name )
2017-09-10 16:57:22 +00:00
}