diff --git a/.gitignore b/.gitignore
index 0bce5491f5..b1a288baa0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,3 +66,214 @@ clover.xml
###> phpstan/phpstan ###
phpstan.neon
###< phpstan/phpstan ###
+*.vsidx
+
+# Created by http://www.gitignore.io
+
+### VisualStudio ###
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Roslyn cache directories
+*.ide/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding addin-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# If using the old MSBuild-Integrated Package Restore, uncomment this:
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+
+### Windows ###
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+/.vs/mbin/CopilotIndices/17.12.68.61481
+/.vs/mbin/CopilotIndices/17.12.68.61481/CodeChunks.db-shm
+/.vs/mbin/CopilotIndices/17.12.68.61481/CodeChunks.db-wal
+/.vs/mbin/CopilotIndices/17.12.68.61481/SemanticSymbols.db-shm
+/.vs/mbin/CopilotIndices/17.12.68.61481/SemanticSymbols.db-wal
diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json
new file mode 100644
index 0000000000..f8b4888565
--- /dev/null
+++ b/.vs/ProjectSettings.json
@@ -0,0 +1,3 @@
+{
+ "CurrentProjectSetting": null
+}
\ No newline at end of file
diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json
new file mode 100644
index 0000000000..6276052470
--- /dev/null
+++ b/.vs/VSWorkspaceState.json
@@ -0,0 +1,9 @@
+{
+ "ExpandedNodes": [
+ "",
+ "\\templates",
+ "\\templates\\user"
+ ],
+ "SelectedNode": "\\templates\\user\\_user_popover.html.twig",
+ "PreviewInSolutionExplorer": false
+}
\ No newline at end of file
diff --git a/.vs/mbin/CopilotIndices/17.12.68.61481/CodeChunks.db b/.vs/mbin/CopilotIndices/17.12.68.61481/CodeChunks.db
new file mode 100644
index 0000000000..ee8175b37f
Binary files /dev/null and b/.vs/mbin/CopilotIndices/17.12.68.61481/CodeChunks.db differ
diff --git a/.vs/mbin/CopilotIndices/17.12.68.61481/SemanticSymbols.db b/.vs/mbin/CopilotIndices/17.12.68.61481/SemanticSymbols.db
new file mode 100644
index 0000000000..9a46769176
Binary files /dev/null and b/.vs/mbin/CopilotIndices/17.12.68.61481/SemanticSymbols.db differ
diff --git a/.vs/mbin/v17/.wsuo b/.vs/mbin/v17/.wsuo
new file mode 100644
index 0000000000..f600329046
Binary files /dev/null and b/.vs/mbin/v17/.wsuo differ
diff --git a/.vs/mbin/v17/DocumentLayout.backup.json b/.vs/mbin/v17/DocumentLayout.backup.json
new file mode 100644
index 0000000000..ab195d30e2
--- /dev/null
+++ b/.vs/mbin/v17/DocumentLayout.backup.json
@@ -0,0 +1,62 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Michael\\source\\repos\\mbin\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_avatar.html.twig||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:templates\\components\\user_avatar.html.twig||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_inline.html.twig||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:templates\\components\\user_inline.html.twig||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 1,
+ "Children": [
+ {
+ "$type": "Bookmark",
+ "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "user_avatar.html.twig",
+ "DocumentMoniker": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_avatar.html.twig",
+ "RelativeDocumentMoniker": "templates\\components\\user_avatar.html.twig",
+ "ToolTip": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_avatar.html.twig",
+ "RelativeToolTip": "templates\\components\\user_avatar.html.twig",
+ "ViewState": "AgIAAA8AAAAAAAAAAAAAAC8AAAAEAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-03-14T17:27:49.905Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Bookmark",
+ "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "user_inline.html.twig",
+ "DocumentMoniker": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_inline.html.twig",
+ "RelativeDocumentMoniker": "templates\\components\\user_inline.html.twig",
+ "ToolTip": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_inline.html.twig",
+ "RelativeToolTip": "templates\\components\\user_inline.html.twig",
+ "ViewState": "AgIAAAcAAAAAAAAAAAAAwBAAAAAhAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-03-14T14:48:57.898Z",
+ "EditorCaption": ""
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/mbin/v17/DocumentLayout.json b/.vs/mbin/v17/DocumentLayout.json
new file mode 100644
index 0000000000..8e6924353b
--- /dev/null
+++ b/.vs/mbin/v17/DocumentLayout.json
@@ -0,0 +1,74 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\Michael\\source\\repos\\mbin\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_avatar.html.twig||{8B382828-6202-11D1-8870-0000F87579D2}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:templates\\components\\user_avatar.html.twig||{8B382828-6202-11D1-8870-0000F87579D2}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Michael\\source\\repos\\mbin\\templates\\user\\_user_popover.html.twig||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:templates\\user\\_user_popover.html.twig||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_inline.html.twig||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:templates\\components\\user_inline.html.twig||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 200,
+ "SelectedChildIndex": 2,
+ "Children": [
+ {
+ "$type": "Bookmark",
+ "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}"
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "_user_popover.html.twig",
+ "DocumentMoniker": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\user\\_user_popover.html.twig",
+ "RelativeDocumentMoniker": "templates\\user\\_user_popover.html.twig",
+ "ToolTip": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\user\\_user_popover.html.twig",
+ "RelativeToolTip": "templates\\user\\_user_popover.html.twig",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAAUAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-03-16T14:51:34.856Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "user_avatar.html.twig",
+ "DocumentMoniker": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_avatar.html.twig",
+ "RelativeDocumentMoniker": "templates\\components\\user_avatar.html.twig",
+ "ToolTip": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_avatar.html.twig",
+ "RelativeToolTip": "templates\\components\\user_avatar.html.twig",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABsAAAAIAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-03-14T17:27:49.905Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "user_inline.html.twig",
+ "DocumentMoniker": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_inline.html.twig",
+ "RelativeDocumentMoniker": "templates\\components\\user_inline.html.twig",
+ "ToolTip": "C:\\Users\\Michael\\source\\repos\\mbin\\templates\\components\\user_inline.html.twig",
+ "RelativeToolTip": "templates\\components\\user_inline.html.twig",
+ "ViewState": "AgIAAAcAAAAAAAAAAAAAwBAAAAAhAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
+ "WhenOpened": "2025-03-14T14:48:57.898Z"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vs/mbin/v17/workspaceFileList.bin b/.vs/mbin/v17/workspaceFileList.bin
new file mode 100644
index 0000000000..17052599d1
Binary files /dev/null and b/.vs/mbin/v17/workspaceFileList.bin differ
diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite
new file mode 100644
index 0000000000..14e613c94b
Binary files /dev/null and b/.vs/slnx.sqlite differ
diff --git a/public/default_avatar.png b/public/default_avatar.png
new file mode 100644
index 0000000000..a0ab67d483
Binary files /dev/null and b/public/default_avatar.png differ
diff --git a/templates/components/user_avatar.html.twig b/templates/components/user_avatar.html.twig
index 78621c9e72..d7893719bc 100644
--- a/templates/components/user_avatar.html.twig
+++ b/templates/components/user_avatar.html.twig
@@ -1,19 +1,80 @@
+
+ {% endif %}
+ {% if user.avatar %}
+
+ {% else %}
+ {% set characterMap = {
+ 'a': 2, 'b': 7, 'c': 0, 'd': 8, 'e': 4, 'f': 1, 'g': 3, 'h': 5, 'i': 6, 'j': 9, 'k': 10,
+ 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 0, 'r': 1, 's': 2, 't': 3, 'u': 4, 'v': 5,
+ 'w': 6, 'x': 7, 'y': 8, 'z': 9, '_': 10, '-': 11, '0': 14, '1': 10, '2': 15, '3': 11, '4': 12,
+ '5': 9, '6': 3, '7': 5, '8': 6, '9': 13, 'A': 4, 'B': 8, 'C': 1, 'D': 7, 'E': 2, 'F': 5,
+ 'G': 9, 'H': 0, 'I': 3, 'J': 6, 'K': 11, 'L': 14, 'M': 10, 'N': 15, 'O': 12, 'P': 13, 'Q': 2,
+ 'R': 4, 'S': 7, 'T': 1, 'U': 8, 'V': 5, 'W': 0, 'X': 3, 'Y': 6, 'Z': 9} %}
+
+ {% set R = 0 %}
+ {% set G = 0 %}
+ {% set B = 0 %}
+ {% set index = 0 %}
+ {% set break = false %}
+ {% set validName = user.username|slice(0,6) ~ "012345" %}
+
+ {% for char in validName|split('') %}
+ {% if char in characterMap|keys and index < 6%}
+ {% set value = characterMap[char] %}
+ {% if index == 0 %}
+ {% set R = value * 16 %}
+ {% elseif index == 1 %}
+ {% set R = R + value %}
+ {% elseif index == 2 %}
+ {% set G = value * 16 %}
+ {% elseif index == 3 %}
+ {% set G = G + value %}
+ {% elseif index == 4 %}
+ {% set B = value * 16 %}
+ {% elseif index == 5 %}
+ {% set B = B + value %}
+ {% endif %}
+ {% set index = index + 1 %}
+ {% endif %}
+ {% endfor %}
+
+ {% set R = R / 255 %}
+ {% set G = G / 255 %}
+ {% set B = B / 255 %}
+
+ {% if app.user is defined and app.user is not same as null and app.user is same as user %}
+ {% set noAvatar = "you can set your avatar in your profile" %}
{% else %}
-
+ {% set noAvatar = user.username ~ " has no avatar" %}
{% endif %}
- {% if asLink %}
-
+
+
+
+
+ {% endif %}
+ {% if asLink %}
+
{% endif %}
+
+ {% elseif showAvatar %}
+ {% set characterMap = {
+ 'a': 2, 'b': 7, 'c': 0, 'd': 8, 'e': 4, 'f': 1, 'g': 3, 'h': 5, 'i': 6, 'j': 9, 'k': 10,
+ 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 0, 'r': 1, 's': 2, 't': 3, 'u': 4, 'v': 5,
+ 'w': 6, 'x': 7, 'y': 8, 'z': 9, '_': 10, '-': 11, '0': 14, '1': 10, '2': 15, '3': 11, '4': 12,
+ '5': 9, '6': 3, '7': 5, '8': 6, '9': 13, 'A': 4, 'B': 8, 'C': 1, 'D': 7, 'E': 2, 'F': 5,
+ 'G': 9, 'H': 0, 'I': 3, 'J': 6, 'K': 11, 'L': 14, 'M': 10, 'N': 15, 'O': 12, 'P': 13, 'Q': 2,
+ 'R': 4, 'S': 7, 'T': 1, 'U': 8, 'V': 5, 'W': 0, 'X': 3, 'Y': 6, 'Z': 9} %}
+
+ {% set R = 0 %}
+ {% set G = 0 %}
+ {% set B = 0 %}
+ {% set index = 0 %}
+ {% set break = false %}
+ {% set validName = user.username|slice(0,6) ~ "012345" %}
+
+ {% for char in validName|split('') %}
+ {% if char in characterMap|keys and index < 6%}
+ {% set value = characterMap[char] %}
+ {% if index == 0 %}
+ {% set R = value * 16 %}
+ {% elseif index == 1 %}
+ {% set R = R + value %}
+ {% elseif index == 2 %}
+ {% set G = value * 16 %}
+ {% elseif index == 3 %}
+ {% set G = G + value %}
+ {% elseif index == 4 %}
+ {% set B = value * 16 %}
+ {% elseif index == 5 %}
+ {% set B = B + value %}
+ {% endif %}
+ {% set index = index + 1 %}
+ {% endif %}
+ {% endfor %}
+
+ {% set R = R / 255 %}
+ {% set G = G / 255 %}
+ {% set B = B / 255 %}
+
+ {% if app.user is defined and app.user is not same as null and app.user is same as user %}
+ {% set noAvatar = "you can set your avatar in your profile" %}
+ {% else %}
+ {% set noAvatar = user.username ~ " has no avatar" %}
{% endif %}
+
+
+
+
+
+ {% endif %}
+
{{ user.apPreferredUsername ?? user.username|username -}}
{%- if fullName is defined and fullName is same as true -%}
@{{- user.username|apDomain -}}
{%- endif -%}
- {% if user.isNew() and showNewIcon %}
+ {% if user.isNew() %}
{% set days = constant('App\\Entity\\User::NEW_FOR_DAYS') %}
{% endif %}
diff --git a/templates/user/_user_popover.html.twig b/templates/user/_user_popover.html.twig
index 21a53f1267..c6d5c2a779 100644
--- a/templates/user/_user_popover.html.twig
+++ b/templates/user/_user_popover.html.twig
@@ -1,13 +1,13 @@