Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
a3398f0dd0
commit
c9b1b3cf62
7
PRD.md
7
PRD.md
@ -373,10 +373,13 @@ TheNoiseClock/
|
|||||||
│ │ ├── Debug.xcconfig # Debug settings
|
│ │ ├── Debug.xcconfig # Debug settings
|
||||||
│ │ └── Release.xcconfig # Release settings
|
│ │ └── Release.xcconfig # Release settings
|
||||||
│ ├── Shared/
|
│ ├── Shared/
|
||||||
│ │ ├── BrandingConfig.swift # Bedrock branding + launch config
|
|
||||||
│ │ ├── Design/
|
│ │ ├── Design/
|
||||||
|
│ │ │ ├── BrandingConfig.swift # Bedrock branding + launch config
|
||||||
│ │ │ ├── AppConstants.swift # App-wide constants and configuration
|
│ │ │ ├── AppConstants.swift # App-wide constants and configuration
|
||||||
│ │ │ ├── UIConstants.swift # UI-specific constants (colors, sizes, etc.)
|
│ │ │ ├── UIConstants.swift # UI constants namespace
|
||||||
|
│ │ │ ├── UIConstants+Colors.swift # Theme-backed colors
|
||||||
|
│ │ │ ├── UIConstants+Layout.swift # Spacing/radius/opacity
|
||||||
|
│ │ │ ├── UIConstants+Animation.swift # Animation curves
|
||||||
│ │ │ └── Fonts/
|
│ │ │ └── Fonts/
|
||||||
│ │ │ ├── Font.Design.swift
|
│ │ │ ├── Font.Design.swift
|
||||||
│ │ │ ├── Font.Weight.swift
|
│ │ │ ├── Font.Weight.swift
|
||||||
|
|||||||
@ -87,7 +87,7 @@ xcodebuild -project TheNoiseClock/TheNoiseClock.xcodeproj -scheme TheNoiseClock
|
|||||||
The app uses Bedrock for theme tokens, settings UI, and the launch experience.
|
The app uses Bedrock for theme tokens, settings UI, and the launch experience.
|
||||||
|
|
||||||
- Theme: `TheNoiseClock/Shared/Theme/NoiseClockTheme.swift`
|
- Theme: `TheNoiseClock/Shared/Theme/NoiseClockTheme.swift`
|
||||||
- Branding config: `TheNoiseClock/Shared/BrandingConfig.swift`
|
- Branding config: `TheNoiseClock/Shared/Design/BrandingConfig.swift`
|
||||||
- Launch screen: `TheNoiseClock/Resources/LaunchScreen.storyboard`
|
- Launch screen: `TheNoiseClock/Resources/LaunchScreen.storyboard`
|
||||||
|
|
||||||
To generate an app icon in DEBUG:
|
To generate an app icon in DEBUG:
|
||||||
|
|||||||
@ -32,9 +32,8 @@
|
|||||||
EA384AFB2E6E6B6000CA7D50 /* TheNoiseClock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TheNoiseClock.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA384AFB2E6E6B6000CA7D50 /* TheNoiseClock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TheNoiseClock.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA384B082E6E6B6100CA7D50 /* TheNoiseClockTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TheNoiseClockTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA384B082E6E6B6100CA7D50 /* TheNoiseClockTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TheNoiseClockTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA384B122E6E6B6100CA7D50 /* TheNoiseClockUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TheNoiseClockUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA384B122E6E6B6100CA7D50 /* TheNoiseClockUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TheNoiseClockUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EAD6E3AE5A7F4D3DB37CF6D1 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TheNoiseClock/Configuration/Base.xcconfig; sourceTree = SOURCE_ROOT; };
|
EAD6E3AF5A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TheNoiseClock/Configuration/Debug.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||||
EAD6E3AF5A7F4D3DB37CF6D1 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TheNoiseClock/Configuration/Debug.xcconfig; sourceTree = SOURCE_ROOT; };
|
EAD6E3B05A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TheNoiseClock/Configuration/Release.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||||
EAD6E3B05A7F4D3DB37CF6D1 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TheNoiseClock/Configuration/Release.xcconfig; sourceTree = SOURCE_ROOT; };
|
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
@ -102,6 +101,7 @@
|
|||||||
EA384B0B2E6E6B6100CA7D50 /* TheNoiseClockTests */,
|
EA384B0B2E6E6B6100CA7D50 /* TheNoiseClockTests */,
|
||||||
EA384B152E6E6B6100CA7D50 /* TheNoiseClockUITests */,
|
EA384B152E6E6B6100CA7D50 /* TheNoiseClockUITests */,
|
||||||
EA384AFC2E6E6B6000CA7D50 /* Products */,
|
EA384AFC2E6E6B6000CA7D50 /* Products */,
|
||||||
|
EAC057642F2E69E8007F87EA /* Recovered References */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@ -115,6 +115,15 @@
|
|||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
EAC057642F2E69E8007F87EA /* Recovered References */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
EAD6E3AF5A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Debug.xcconfig */,
|
||||||
|
EAD6E3B05A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Release.xcconfig */,
|
||||||
|
);
|
||||||
|
name = "Recovered References";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -300,7 +309,7 @@
|
|||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
EA384B1A2E6E6B6100CA7D50 /* Debug */ = {
|
EA384B1A2E6E6B6100CA7D50 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* Debug.xcconfig */;
|
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
@ -365,7 +374,7 @@
|
|||||||
};
|
};
|
||||||
EA384B1B2E6E6B6100CA7D50 /* Release */ = {
|
EA384B1B2E6E6B6100CA7D50 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* Release.xcconfig */;
|
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
@ -423,7 +432,7 @@
|
|||||||
};
|
};
|
||||||
EA384B1D2E6E6B6100CA7D50 /* Debug */ = {
|
EA384B1D2E6E6B6100CA7D50 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* Debug.xcconfig */;
|
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
@ -457,7 +466,7 @@
|
|||||||
};
|
};
|
||||||
EA384B1E2E6E6B6100CA7D50 /* Release */ = {
|
EA384B1E2E6E6B6100CA7D50 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* Release.xcconfig */;
|
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
@ -491,7 +500,7 @@
|
|||||||
};
|
};
|
||||||
EA384B202E6E6B6100CA7D50 /* Debug */ = {
|
EA384B202E6E6B6100CA7D50 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* Debug.xcconfig */;
|
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@ -514,7 +523,7 @@
|
|||||||
};
|
};
|
||||||
EA384B212E6E6B6100CA7D50 /* Release */ = {
|
EA384B212E6E6B6100CA7D50 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* Release.xcconfig */;
|
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
@ -537,7 +546,7 @@
|
|||||||
};
|
};
|
||||||
EA384B232E6E6B6100CA7D50 /* Debug */ = {
|
EA384B232E6E6B6100CA7D50 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* Debug.xcconfig */;
|
baseConfigurationReference = EAD6E3AF5A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -558,7 +567,7 @@
|
|||||||
};
|
};
|
||||||
EA384B242E6E6B6100CA7D50 /* Release */ = {
|
EA384B242E6E6B6100CA7D50 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* Release.xcconfig */;
|
baseConfigurationReference = EAD6E3B05A7F4D3DB37CF6D1 /* TheNoiseClock/Configuration/Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<key>TheNoiseClock.xcscheme_^#shared#^_</key>
|
<key>TheNoiseClock.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>2</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
19
TheNoiseClock/Shared/Design/UIConstants+Animation.swift
Normal file
19
TheNoiseClock/Shared/Design/UIConstants+Animation.swift
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// UIConstants+Animation.swift
|
||||||
|
// TheNoiseClock
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 1/31/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Bedrock
|
||||||
|
|
||||||
|
extension UIConstants {
|
||||||
|
|
||||||
|
// MARK: - Animation Curves
|
||||||
|
enum AnimationCurves {
|
||||||
|
static let smooth = Animation.smooth(duration: Design.Animation.standard)
|
||||||
|
static let bouncy = Animation.spring(duration: Design.Animation.springDuration, bounce: Design.Animation.springBounce)
|
||||||
|
static let quick = Animation.easeInOut(duration: Design.Animation.quick)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
TheNoiseClock/Shared/Design/UIConstants+Colors.swift
Normal file
21
TheNoiseClock/Shared/Design/UIConstants+Colors.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// UIConstants+Colors.swift
|
||||||
|
// TheNoiseClock
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 1/31/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension UIConstants {
|
||||||
|
|
||||||
|
// MARK: - Colors
|
||||||
|
enum Colors {
|
||||||
|
static let accentColor = AppAccent.primary
|
||||||
|
static let primaryText = AppTextColors.primary
|
||||||
|
static let secondaryText = AppTextColors.secondary
|
||||||
|
static let background = AppSurface.primary
|
||||||
|
static let overlayBackground = AppSurface.overlay
|
||||||
|
static let overlayBorder = AppBorder.subtle
|
||||||
|
}
|
||||||
|
}
|
||||||
45
TheNoiseClock/Shared/Design/UIConstants+Layout.swift
Normal file
45
TheNoiseClock/Shared/Design/UIConstants+Layout.swift
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// UIConstants+Layout.swift
|
||||||
|
// TheNoiseClock
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 1/31/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Bedrock
|
||||||
|
|
||||||
|
extension UIConstants {
|
||||||
|
|
||||||
|
// MARK: - Spacing
|
||||||
|
enum Spacing {
|
||||||
|
static let extraSmall: CGFloat = Design.Spacing.xSmall
|
||||||
|
static let small: CGFloat = Design.Spacing.small
|
||||||
|
static let medium: CGFloat = Design.Spacing.medium
|
||||||
|
static let large: CGFloat = Design.Spacing.large
|
||||||
|
static let extraLarge: CGFloat = Design.Spacing.xLarge
|
||||||
|
static let huge: CGFloat = Design.Spacing.xxLarge
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Corner Radius
|
||||||
|
enum CornerRadius {
|
||||||
|
static let small: CGFloat = Design.CornerRadius.small
|
||||||
|
static let medium: CGFloat = Design.CornerRadius.large
|
||||||
|
static let large: CGFloat = 16
|
||||||
|
static let extraLarge: CGFloat = Design.CornerRadius.xxLarge
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Border Width
|
||||||
|
enum BorderWidth {
|
||||||
|
static let thin: CGFloat = Design.LineWidth.hairline
|
||||||
|
static let normal: CGFloat = Design.LineWidth.thin
|
||||||
|
static let thick: CGFloat = Design.LineWidth.standard
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Opacity
|
||||||
|
enum Opacity {
|
||||||
|
static let disabled: Double = Design.Opacity.light
|
||||||
|
static let secondary: Double = Design.Opacity.accent
|
||||||
|
static let primary: Double = Design.Opacity.heavy
|
||||||
|
static let full: Double = 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,71 +7,5 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
/// UI-specific constants for colors, sizes, and styling
|
/// UI-specific constants for styling and layout.
|
||||||
enum UIConstants {
|
enum UIConstants {}
|
||||||
|
|
||||||
// MARK: - Colors
|
|
||||||
enum Colors {
|
|
||||||
static let accentColor = Color.blue
|
|
||||||
static let primaryText = Color.white
|
|
||||||
static let secondaryText = Color.gray
|
|
||||||
static let background = Color.black
|
|
||||||
static let overlayBackground = Color.black.opacity(0.25)
|
|
||||||
static let overlayBorder = Color.white.opacity(0.05)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Font Sizes
|
|
||||||
enum FontSizes {
|
|
||||||
static let largeTitle: CGFloat = 34
|
|
||||||
static let title: CGFloat = 28
|
|
||||||
static let title2: CGFloat = 22
|
|
||||||
static let title3: CGFloat = 20
|
|
||||||
static let headline: CGFloat = 17
|
|
||||||
static let body: CGFloat = 17
|
|
||||||
static let callout: CGFloat = 16
|
|
||||||
static let subheadline: CGFloat = 15
|
|
||||||
static let footnote: CGFloat = 13
|
|
||||||
static let caption: CGFloat = 12
|
|
||||||
static let caption2: CGFloat = 11
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Spacing
|
|
||||||
enum Spacing {
|
|
||||||
static let extraSmall: CGFloat = 4
|
|
||||||
static let small: CGFloat = 8
|
|
||||||
static let medium: CGFloat = 12
|
|
||||||
static let large: CGFloat = 16
|
|
||||||
static let extraLarge: CGFloat = 20
|
|
||||||
static let huge: CGFloat = 24
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Corner Radius
|
|
||||||
enum CornerRadius {
|
|
||||||
static let small: CGFloat = 8
|
|
||||||
static let medium: CGFloat = 12
|
|
||||||
static let large: CGFloat = 16
|
|
||||||
static let extraLarge: CGFloat = 20
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Border Width
|
|
||||||
enum BorderWidth {
|
|
||||||
static let thin: CGFloat = 0.5
|
|
||||||
static let normal: CGFloat = 1
|
|
||||||
static let thick: CGFloat = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Opacity
|
|
||||||
enum Opacity {
|
|
||||||
static let disabled: Double = 0.3
|
|
||||||
static let secondary: Double = 0.6
|
|
||||||
static let primary: Double = 0.8
|
|
||||||
static let full: Double = 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Animation Curves
|
|
||||||
enum AnimationCurves {
|
|
||||||
static let smooth = Animation.smooth(duration: AppConstants.AnimationDurations.medium)
|
|
||||||
static let bouncy = Animation.bouncy(duration: AppConstants.AnimationDurations.bouncy)
|
|
||||||
static let quick = Animation.easeInOut(duration: AppConstants.AnimationDurations.short)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user