Make flake self-contained - consolidate installer-replication

BREAKING CHANGE: Remove external dots-hyprland dependency

- Imported all essential configs from dots-hyprland/installer-replication
- Added complete configs/ directory with:
  - hypr/ - Hyprland configuration
  - quickshell/ - Quickshell widgets and config
  - applications/ - Application configurations
  - scripts/ - Utility scripts
  - matugen/ - Material You theming
- Updated flake.nix to use local ./configs instead of external repo
- Simplified update-flake script (removed external repo management)
- Updated README to reflect self-contained architecture
- All builds pass with local configurations

Benefits:
- No external repository dependencies
- Faster builds (no network dependencies)
- Version controlled configs in single repo
- Easier maintenance and development
- Complete installer replication in one place
This commit is contained in:
Celes Renata
2025-08-08 22:26:47 -07:00
parent 22b65891ac
commit ac6d3adeb9
710 changed files with 81319 additions and 115 deletions
+99
View File
@@ -0,0 +1,99 @@
import qs
import qs.modules.common
import qs.modules.common.functions
import qs.modules.lock
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import Quickshell.Hyprland
Scope {
id: root
// This stores all the information shared between the lock surfaces on each screen.
// https://github.com/quickshell-mirror/quickshell-examples/tree/master/lockscreen
LockContext {
id: lockContext
onUnlocked: {
// Unlock the screen before exiting, or the compositor will display a
// fallback lock you can't interact with.
GlobalStates.screenLocked = false;
}
}
WlSessionLock {
id: lock
locked: GlobalStates.screenLocked
WlSessionLockSurface {
color: "transparent"
Loader {
active: GlobalStates.screenLocked
anchors.fill: parent
opacity: active ? 1 : 0
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
sourceComponent: LockSurface {
context: lockContext
}
}
}
}
// Blur layer hack
Variants {
model: Quickshell.screens
LazyLoader {
id: blurLayerLoader
required property var modelData
active: GlobalStates.screenLocked
component: PanelWindow {
screen: blurLayerLoader.modelData
WlrLayershell.namespace: "quickshell:lockWindowPusher"
color: "transparent"
anchors {
top: true
left: true
right: true
}
// implicitHeight: lockContext.currentText == "" ? 1 : screen.height
implicitHeight: 1
exclusiveZone: screen.height * 3 // For some reason if we don't multiply by some number it would look really weird
}
}
}
IpcHandler {
target: "lock"
function activate(): void {
GlobalStates.screenLocked = true;
}
function focus(): void {
lockContext.shouldReFocus();
}
}
GlobalShortcut {
name: "lock"
description: "Locks the screen"
onPressed: {
GlobalStates.screenLocked = true;
}
}
GlobalShortcut {
name: "lockFocus"
description: "Re-focuses the lock screen. This is because Hyprland after waking up for whatever reason"
+ "decides to keyboard-unfocus the lock screen"
onPressed: {
// console.log("I BEG FOR PLEAS REFOCUZ")
lockContext.shouldReFocus();
}
}
}
@@ -0,0 +1,67 @@
import qs
import QtQuick
import Quickshell
import Quickshell.Services.Pam
Scope {
id: root
signal shouldReFocus()
signal unlocked()
signal failed()
// These properties are in the context and not individual lock surfaces
// so all surfaces can share the same state.
property string currentText: ""
property bool unlockInProgress: false
property bool showFailure: false
Timer {
id: passwordClearTimer
interval: 10000
onTriggered: {
root.currentText = "";
}
}
onCurrentTextChanged: {
showFailure = false; // Clear the failure text once the user starts typing.
GlobalStates.screenLockContainsCharacters = currentText.length > 0;
passwordClearTimer.restart();
}
function tryUnlock() {
if (currentText === "") return;
root.unlockInProgress = true;
pam.start();
}
PamContext {
id: pam
// Its best to have a custom pam config for quickshell, as the system one
// might not be what your interface expects, and break in some way.
// This particular example only supports passwords.
configDirectory: "pam"
config: "password.conf"
// pam_unix will ask for a response for the password prompt
onPamMessage: {
if (this.responseRequired) {
this.respond(root.currentText);
}
}
// pam_unix won't send any important messages so all we need is the completion status.
onCompleted: result => {
if (result == PamResult.Success) {
root.unlocked();
} else {
root.showFailure = true;
}
root.currentText = "";
root.unlockInProgress = false;
}
}
}
@@ -0,0 +1,147 @@
import QtQuick
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
MouseArea {
id: root
required property LockContext context
property bool active: false
property bool showInputField: active || context.currentText.length > 0
function forceFieldFocus() {
passwordBox.forceActiveFocus();
}
Component.onCompleted: {
forceFieldFocus();
}
Connections {
target: context
function onShouldReFocus() {
forceFieldFocus();
}
}
Keys.onPressed: (event) => { // Esc to clear
// console.log("KEY!!")
if (event.key === Qt.Key_Escape) {
root.context.currentText = ""
}
forceFieldFocus();
}
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onPressed: (mouse) => {
forceFieldFocus();
// console.log("Pressed")
}
onPositionChanged: (mouse) => {
forceFieldFocus();
// console.log(JSON.stringify(mouse))
}
anchors.fill: parent
// RippleButton {
// anchors {
// top: parent.top
// left: parent.left
// leftMargin: 10
// topMargin: 10
// }
// implicitHeight: 40
// colBackground: Appearance.colors.colLayer2
// onClicked: context.unlocked()
// contentItem: StyledText {
// text: "[[ DEBUG BYPASS ]]"
// }
// }
// Password entry
Rectangle {
id: passwordBoxContainer
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: root.showInputField ? 20 : -height
}
Behavior on anchors.bottomMargin {
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
}
radius: Appearance.rounding.full
color: Appearance.colors.colLayer2
implicitWidth: 160
implicitHeight: 44
StyledText {
visible: root.context.showFailure && passwordBox.text.length == 0
anchors.centerIn: parent
text: "Incorrect"
color: Appearance.m3colors.m3error
}
StyledTextInput {
id: passwordBox
anchors {
fill: parent
margins: 10
}
clip: true
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
focus: true
onFocusChanged: root.forceFieldFocus();
color: Appearance.colors.colOnLayer2
font {
pixelSize: 10
}
// Password
enabled: !root.context.unlockInProgress
echoMode: TextInput.Password
inputMethodHints: Qt.ImhSensitiveData
// Synchronizing (across monitors) and unlocking
onTextChanged: root.context.currentText = this.text
onAccepted: root.context.tryUnlock()
Connections {
target: root.context
function onCurrentTextChanged() {
passwordBox.text = root.context.currentText;
}
}
}
}
RippleButton {
anchors {
verticalCenter: passwordBoxContainer.verticalCenter
left: passwordBoxContainer.right
leftMargin: 5
}
visible: opacity > 0
implicitHeight: passwordBoxContainer.implicitHeight - 12
implicitWidth: implicitHeight
toggled: true
buttonRadius: passwordBoxContainer.radius
colBackground: Appearance.colors.colLayer2
onClicked: root.context.tryUnlock()
contentItem: MaterialSymbol {
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
iconSize: 24
text: "arrow_right_alt"
color: Appearance.colors.colOnPrimary
}
}
}
@@ -0,0 +1 @@
auth required pam_unix.so