Skip to content

Commit

Permalink
#26 change hold-to-select chars to reflect new callout design
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtavis committed Feb 25, 2022
1 parent b6b0424 commit 4ddcf02
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 82 deletions.
16 changes: 8 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ Emojis for the following are chosen based on [gitmoji](https://gitmoji.dev/).
- The messages that tell the user a noun is already plural have been translated to the keyboard's language.
- The keyboard height has been increased for landscape mode on iPads.
- Characters on keys have been made larger so they reflect the system keyboards better.
- All letter, number and special keys now pop up after being pressed.
<!--- Hold to select characters have been redesigned to reflect the addition of keys popping up. -->
- All letter, number and special keys now pop up after being pressed.
- Hold to select characters have been redesigned to reflect the addition of keys popping up.
<!--- All App Store media has been redone to reflect these changes.-->

# Scribe 1.2.1

### ✨ New Features

- The keyboard switches back to letter keys after all appropriate symbols followed by space.
- Scribe commands now accept inputs that are followed by a space in case the user accidentally added one.
- Users can now translate pronouns as these were not originally included.

### 🗃️ Data Added

- French: 30 nouns, 1 verb
Expand All @@ -48,12 +54,6 @@ Emojis for the following are chosen based on [gitmoji](https://gitmoji.dev/).
- Spanish: 925 nouns, 19 verbs
- Swedish: 10 nouns, 5 verbs

### ✨ New Features

- The keyboard switches back to letter keys after all appropriate symbols followed by space.
- Scribe commands now accept inputs that are followed by a space in case the user accidentally added one.
- Users can now translate pronouns as these were not originally included.

### 🎨 Design Changes

- The app screen texts are given slightly more room to expand within their fields.
Expand Down
240 changes: 239 additions & 1 deletion Keyboards/KeyboardsBase/KeyAltChars.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ func setKeyboardAlternateKeys() {
}

var alternatesKeyView: UIView!
var alternatesShapeLayer = CAShapeLayer()
var keyCancelled = false
var keysWithAlternates = [String]()
var alternateKeys = [String]()

// Variables for alternate key view appearance.
var alternateBtnStartX = CGFloat(0)
var alternatesViewWidth = CGFloat(0)
var alternateKeyWidth = CGFloat(0)
var alternatesLongWidth = CGFloat(0)
var alternatesViewX = CGFloat(0)
var alternatesViewY = CGFloat(0)
var alternatesBtnHeight = CGFloat(0)
Expand Down Expand Up @@ -98,3 +99,240 @@ var dAlternateKeys = [String]()
var cAlternateKeys = [String]()
var nAlternateKeys = [String]()
var ьAlternateKeys = [String]()

/// Creates the shape that allows left most buttons to pop up after being pressed.
///
/// - Parameters
/// - startX: the x-axis starting point.
/// - startY: the y-axis starting point.
/// - keyHeight: the height of the key.
/// - numAlternates: the number of alternate characters to display.
/// - side: the side of the keyboard that the key is found.
func setAlternatesPathState(
startX: CGFloat,
startY: CGFloat,
keyHeight: CGFloat,
numAlternates: CGFloat,
side: String
) {
// Starting positions need to be updated.
horizStart = startX
vertStart = startY + keyHeight
if DeviceType.isPad {
widthMultiplier = 0.2
maxHeightMultiplier = 2.05
if isLandscapeView == true {
maxHeightMultiplier = 1.95
}
} else if DeviceType.isPhone {
widthMultiplier = 0.4
maxHeightMultiplier = 2.125
if isLandscapeView == true {
widthMultiplier = 0.2
}
}

maxHeight = vertStart - ( keyHeight * maxHeightMultiplier )
maxHeightCurveControl = vertStart - ( keyHeight * ( maxHeightMultiplier - 0.125 ))
minHeightCurveControl = vertStart - ( keyHeight * 0.005 )

if DeviceType.isPhone {
heightBeforeTopCurves = vertStart - ( keyHeight * 1.8 )
} else if DeviceType.isPad || ( DeviceType.isPhone && isLandscapeView == true ) {
heightBeforeTopCurves = vertStart - ( keyHeight * 1.6 )
}
if side == "left" {
alternatesLongWidth = horizStart + ( keyWidth * numAlternates + ( 3.0 * numAlternates ) + 8.0 )
} else if side == "right" {
alternatesLongWidth = horizStart + keyWidth - CGFloat(keyWidth * numAlternates + ( 3.0 * numAlternates ) + 1.0)
}

alternatesShapeLayer.strokeColor = keyShadowColor
alternatesShapeLayer.fillColor = keyColor.cgColor
alternatesShapeLayer.lineWidth = 1.0
}

/// Creates the shape that allows alternate keys to be displayed to the user for keys on the left side of the keyboard.
///
/// - Parameters
/// - startX: the x-axis starting point.
/// - startY: the y-axis starting point.
/// - keyWidth: the width of the key.
/// - keyHeight: the height of the key.
/// - numAlternates: the number of alternate characters to display.
func alternateKeysPathLeft(
startX: CGFloat,
startY: CGFloat,
keyWidth: CGFloat,
keyHeight: CGFloat,
numAlternates: CGFloat
) -> UIBezierPath {
setAlternatesPathState(
startX: startX, startY: startY, keyHeight: keyHeight, numAlternates: numAlternates, side: "left"
)

// Path is clockwise from bottom left.
let path = UIBezierPath()
path.move(to: CGPoint(x: horizStart + ( keyWidth * 0.075 ), y: vertStart))

// Curve up past bottom left, path up, and curve out to the left.
path.addCurve(to: CGPoint(x: horizStart, y: vertStart - ( keyHeight * 0.075 )),
controlPoint1: CGPoint(x: horizStart + ( keyWidth * 0.075 ), y: minHeightCurveControl),
controlPoint2: CGPoint(x: horizStart, y: minHeightCurveControl))
path.addLine(to: CGPoint(x: horizStart, y: vertStart - ( keyHeight * 0.85 )))
path.addCurve(to: CGPoint(x: horizStart - ( keyWidth * widthMultiplier ), y: vertStart - ( keyHeight * 1.2 )),
controlPoint1: CGPoint(x: horizStart, y: vertStart - ( keyHeight * 0.9 )),
controlPoint2: CGPoint(
x: horizStart - ( keyWidth * widthMultiplier ),
y: vertStart - ( keyHeight * 1.05 )))

// Path up and curve right past the top left.
path.addLine(to: CGPoint(x: horizStart - ( keyWidth * widthMultiplier ), y: heightBeforeTopCurves))
path.addCurve(to: CGPoint(x: horizStart + ( keyWidth * 0.075 ), y: maxHeight),
controlPoint1: CGPoint(x: horizStart - ( keyWidth * widthMultiplier ), y: maxHeightCurveControl),
controlPoint2: CGPoint(x: horizStart - ( keyWidth * 0.25 ), y: maxHeight))

// Path right, curve down past the top right, and path down.
path.addLine(to: CGPoint(x: alternatesLongWidth - ( keyWidth * 0.5 ), y: maxHeight))
path.addCurve(to: CGPoint(x: alternatesLongWidth, y: heightBeforeTopCurves),
controlPoint1: CGPoint(x: alternatesLongWidth - ( keyWidth * 0.2 ), y: maxHeight),
controlPoint2: CGPoint(x: alternatesLongWidth, y: maxHeightCurveControl))
path.addLine(to: CGPoint(x: alternatesLongWidth, y: vertStart - ( keyHeight * 1.15 )))

// Curve down past the left and path left.
path.addCurve(to: CGPoint(x: alternatesLongWidth - ( keyWidth * 0.5 ), y: vertStart - ( keyHeight * 0.95 )),
controlPoint1: CGPoint(x: alternatesLongWidth, y: vertStart - ( keyHeight * 1.05 )),
controlPoint2: CGPoint(x: alternatesLongWidth - ( keyWidth * 0.2 ), y: vertStart - ( keyHeight * 0.95 )))
path.addLine(to: CGPoint(x: horizStart + ( keyWidth * 1.15 ), y: vertStart - ( keyHeight * 0.95 )))

// Curve in to the left, go down, and curve down past bottom left.
path.addCurve(to: CGPoint(x: horizStart + keyWidth, y: vertStart - ( keyHeight * 0.85 )),
controlPoint1: CGPoint(x: horizStart + ( keyWidth * 1.05 ), y: vertStart - ( keyHeight * 0.95 )),
controlPoint2: CGPoint(x: horizStart + keyWidth, y: vertStart - ( keyHeight * 0.875 )))
path.addLine(to: CGPoint(x: horizStart + keyWidth, y: vertStart - ( keyHeight * 0.075 )))
path.addCurve(to: CGPoint(x: horizStart + ( keyWidth * 0.925 ), y: vertStart),
controlPoint1: CGPoint(x: horizStart + keyWidth, y: minHeightCurveControl),
controlPoint2: CGPoint(x: horizStart + ( keyWidth * 0.925 ), y: minHeightCurveControl))

path.close()
return path
}

/// Creates the shape that allows alternate keys to be displayed to the user for keys on the left side of the keyboard.
///
/// - Parameters
/// - startX: the x-axis starting point.
/// - startY: the y-axis starting point.
/// - keyWidth: the width of the key.
/// - keyHeight: the height of the key.
/// - numAlternates: the number of alternate characters to display.
func alternateKeysPathRight(
startX: CGFloat,
startY: CGFloat,
keyWidth: CGFloat,
keyHeight: CGFloat,
numAlternates: CGFloat
) -> UIBezierPath {
setAlternatesPathState(
startX: startX, startY: startY, keyHeight: keyHeight, numAlternates: numAlternates, side: "right"
)

// Path is clockwise from bottom left.
let path = UIBezierPath()
path.move(to: CGPoint(x: horizStart + ( keyWidth * 0.075 ), y: vertStart))

// Curve up past bottom left, path up, and curve out to the left.
path.addCurve(to: CGPoint(x: horizStart, y: vertStart - ( keyHeight * 0.075 )),
controlPoint1: CGPoint(x: horizStart + ( keyWidth * 0.075 ), y: minHeightCurveControl),
controlPoint2: CGPoint(x: horizStart, y: minHeightCurveControl))
path.addLine(to: CGPoint(x: horizStart, y: vertStart - ( keyHeight * 0.85 )))
path.addCurve(to: CGPoint(x: horizStart - ( keyWidth * 0.15 ), y: vertStart - ( keyHeight * 0.95 )),
controlPoint1: CGPoint(x: horizStart, y: vertStart - ( keyHeight * 0.875 )),
controlPoint2: CGPoint(x: horizStart - ( keyWidth * 0.05 ), y: vertStart - ( keyHeight * 0.95 )))

// Path left and path up past the left.
path.addLine(to: CGPoint(x: alternatesLongWidth + ( keyWidth * 0.5 ), y: vertStart - ( keyHeight * 0.95 )))
path.addCurve(to: CGPoint(x: alternatesLongWidth, y: vertStart - ( keyHeight * 1.15 )),
controlPoint1: CGPoint(
x: alternatesLongWidth + ( keyWidth * 0.2 ),
y: vertStart - ( keyHeight * 0.95 )),
controlPoint2: CGPoint(x: alternatesLongWidth, y: vertStart - ( keyHeight * 1.05 )))

// Path up and curve up past the top left.
path.addLine(to: CGPoint(x: alternatesLongWidth, y: heightBeforeTopCurves))
path.addCurve(to: CGPoint(x: alternatesLongWidth + ( keyWidth * 0.5 ), y: maxHeight),
controlPoint1: CGPoint(x: alternatesLongWidth, y: maxHeightCurveControl),
controlPoint2: CGPoint(x: alternatesLongWidth + ( keyWidth * 0.2 ), y: maxHeight))

// Path right, curve down past the top right, and path down.
path.addLine(to: CGPoint(x: horizStart + ( keyWidth * 0.925 ), y: maxHeight))
path.addCurve(to: CGPoint(x: horizStart + ( keyWidth * ( 1 + widthMultiplier )), y: heightBeforeTopCurves),
controlPoint1: CGPoint(x: horizStart + ( keyWidth * 1.25 ), y: maxHeight),
controlPoint2: CGPoint(x: horizStart + ( keyWidth * ( 1 + widthMultiplier )), y: maxHeightCurveControl))
path.addLine(to: CGPoint(x: horizStart + ( keyWidth * ( 1 + widthMultiplier )), y: vertStart - ( keyHeight * 1.2 )))

// Curve in to the left, go down, and curve down past bottom left.
path.addCurve(to: CGPoint(x: horizStart + keyWidth, y: vertStart - ( keyHeight * 0.85 )),
controlPoint1: CGPoint(
x: horizStart + ( keyWidth * ( 1 + widthMultiplier )),
y: vertStart - ( keyHeight * 1.05 )),
controlPoint2: CGPoint(x: horizStart + keyWidth, y: vertStart - ( keyHeight * 0.9 )))
path.addLine(to: CGPoint(x: horizStart + keyWidth, y: vertStart - ( keyHeight * 0.075 )))
path.addCurve(to: CGPoint(x: horizStart + ( keyWidth * 0.925 ), y: vertStart),
controlPoint1: CGPoint(x: horizStart + keyWidth, y: minHeightCurveControl),
controlPoint2: CGPoint(x: horizStart + ( keyWidth * 0.925 ), y: minHeightCurveControl))

path.close()
return path
}

/// Generates an alternates view to select other characters related to a long held key.
///
/// - Parameters
/// - sender: the long press of the given key.
func genAlternatesView(key: UIButton) {
// Get the frame in respect to the superview.
let frame: CGRect = (key.superview?.convert(key.frame, to: nil))!

// Derive which button was pressed and get its alternates.
let char: String = key.layer.value(forKey: "original") as? String ?? ""
alternateKeys = keyAlternatesDict[char ] ?? [""]

// Add the original key given its location on the keyboard.
if keysWithAlternatesLeft.contains(char) {
alternateKeys.insert(char, at: 0)
} else if keysWithAlternatesRight.contains(char) {
alternateKeys.append(char)
}
let numAlternates: CGFloat = CGFloat(alternateKeys.count)

if keysWithAlternatesLeft.contains(char ) {
alternatesViewX = frame.origin.x - 4.0
alternatesShapeLayer.path = alternateKeysPathLeft(
startX: frame.origin.x, startY: frame.origin.y,
keyWidth: key.frame.width, keyHeight: key.frame.height, numAlternates: numAlternates).cgPath
} else if keysWithAlternatesRight.contains(char ) {
alternatesViewX = frame.origin.x + keyWidth - CGFloat(keyWidth * numAlternates + ( 3.0 * numAlternates ) + 2.0)
alternatesShapeLayer.path = alternateKeysPathRight(
startX: frame.origin.x, startY: frame.origin.y,
keyWidth: key.frame.width, keyHeight: key.frame.height, numAlternates: numAlternates).cgPath
}

if numAlternates > 0 {
alternatesViewWidth = CGFloat(keyWidth * numAlternates + ( 3.0 * numAlternates ) + 8.0)
}

alternatesViewY = frame.origin.y - key.frame.height * 1.135
alternatesBtnHeight = key.frame.height * 0.9
alternatesKeyView = UIView(
frame: CGRect(
x: alternatesViewX,
y: alternatesViewY,
width: alternatesViewWidth,
height: key.frame.height * 1.2
)
)

alternatesKeyView.tag = 1001
key.backgroundColor = keyColor
}
1 change: 0 additions & 1 deletion Keyboards/KeyboardsBase/KeyAnimation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ var keyHoldPopLayer = CAShapeLayer()
/// - Parameters
/// - startX: the x-axis starting point.
/// - startY: the y-axis starting point.
/// - keyWidth: the width of the key.
/// - keyHeight: the height of the key.
/// - char: the character of the key.
/// - position: the position of the key.
Expand Down
Loading

0 comments on commit 4ddcf02

Please sign in to comment.