RxSwiftCommunity / RxCocoa-Texture

RxCocoa Extension Library for Texture.
MIT License
100 stars 52 forks source link

Convert ASControlNode.rx.isHighlighted to ControlProperty #23

Closed innocarpe closed 5 years ago

innocarpe commented 5 years ago

I need to observe isHighlighted of an ASControlNode instance to change the state of another node. (Like the situation that I want to show the dimmed ASDisplayNode when I'm pressing a ASControlNode)

That's why propose this because there is a solution for this situation ☺️

This change is tested on our company's project at least (the feature where I'm working on).

innocarpe commented 5 years ago

@OhKanghoon Could you look into this when you're available? 🙏

innocarpe commented 5 years ago

And it can be tested like this (for ControlEvent part).

// given
var isHighlighted: Bool = false
let disposeBag = DisposeBag()
let node = ASControlNode()
expect(node.isHighlighted) == false

node.rx.isHighlighted
  .subscribe(onNext: { isHighlighted = $0 })
  .disposed(by: disposeBag)

// when & then
node.isHighlighted = true
expect(isHighlighted) == true

node.isHighlighted = false
expect(isHighlighted) == false
innocarpe commented 5 years ago

Thanks to @tokijh

innocarpe commented 5 years ago

@GeekTree0101 It'll be grateful to review this ☺️

innocarpe commented 5 years ago

@OhKanghoon I added tests for the new feature.

OhKanghoon commented 5 years ago

How about creating controlProperty function?

controlProperty

    /// Creates a `ControlProperty` that is triggered by target/action pattern value updates.
    ///
    /// - parameter controlEvents: ASControlNodeEvents that trigger value update sequence elements.
    /// - parameter getter: Property value getter.
    /// - parameter setter: Property value setter.
    public func controlProperty<T>(
        editingEvents: ASControlNodeEvent,
        getter: @escaping (Base) -> T,
        setter: @escaping (Base, T) -> ()
    ) -> ControlProperty<T> {
        let source: Observable<T> = Observable.create { [weak weakControl = base] observer in
            guard let control = weakControl else {
                observer.on(.completed)
                return Disposables.create()
            }

            observer.on(.next(getter(control)))

            let controlTarget = ASControlTarget(control, editingEvents) { _ in
                if let control = weakControl {
                    observer.on(.next(getter(control)))
                }
            }

            return Disposables.create(with: controlTarget.dispose)
        }
        .takeUntil(deallocated)

        let bindingObserver = ASBinder(base, binding: setter)

        return ControlProperty<T>(values: source, valueSink: bindingObserver)
    }

isHighlighted

  public var isHighlighted: ControlProperty<Bool> {

    return self.controlProperty(
        editingEvents: [.touchDown, .touchDownRepeat, .touchUpInside, .touchCancel],
        getter: { control in
            control.isHighlighted
        },
        setter: { control, isHighlighted in
            control.isHighlighted = isHighlighted
        }
    )
  }
innocarpe commented 5 years ago

@OhKanghoon Thank you for the feedback. I updated the codes.

rxswiftcommunity[bot] commented 5 years ago
Fails
:no_entry_sign: Danger failed to run `/app/danger-0.54wrw6ohucc.ts`.

Error Error

{"message":"Bad credentials","documentation_url":"https://developer.github.com/v3"}
undefined

Dangerfile

// Removed import

// Hey there!
//
// When a PR is opened, this file gets run. You can add all your rules here, but
// remember that they'll be applied to every pull request on every repo in the
// RxSwiftCommunity organization, so we better write some unit tests!
//
// Note that all the rules have to be async functions.
//
// Follow the changelog example and ignore the next four const lines.
// The inspiration for this is https://github.com/artsy/artsy-danger/blob/f019ee1a3abffabad65014afabe07cb9a12274e7/org/all-prs.ts
const isJest = typeof jest !== "undefined"
// Returns the promise itself, for testing.
const _test = (reason: string, promise: Promise<any>) => promise
// Schedules the promise for execution via Danger.
const _run = (reason: string, promise: Promise<any>) => schedule(promise)
const wrap: any = isJest ? _test : _run

// Inspiration: https://github.com/artsy/artsy-danger/blob/f019ee1a3abffabad65014afabe07cb9a12274e7/org/all-prs.ts#L67-L85
export const changelog = wrap("Require changelog entries on PRs with code changes", async () => {
  // First we check if there is a changelog in the repository.
  const pr = danger.github.pr
  const changelogs = ["CHANGELOG.md", "changelog.md", "Changelog.md", "CHANGELOG.yml"]

  const getContentParams = { path: "", owner: pr.head.user.login, repo: pr.head.repo.name }
  const rootContents: any = await danger.github.api.repos.getContent(getContentParams)

  const hasChangelog = rootContents.data.find((file: any) => changelogs.includes(file.name))
  const markedTrivial = (pr.title + pr.body).includes("#trivial")
  if (hasChangelog) {
    const files = [...danger.git.modified_files, ...danger.git.created_files]

    // Look for Swift files that aren't in a unit test directory.
    const hasCodeChanges = files.find((file: any) => file.match(/.*\.swift/) && !file.match(/(test|spec)/i))
    const hasChangelogChanges = files.find(file => changelogs.includes(file))
    if (!!hasCodeChanges && !hasChangelogChanges) {
      const baseMessage = "It looks like code was changed without adding anything to the Changelog. "
      if (markedTrivial) {
        markdown(baseMessage)
      } else {
        warn(baseMessage + "If this is a trivial PR that doesn't need a changelog, add #trivial to the PR title or body.")
      }
    }
  }
})

Thanks a lot for contributing @innocarpe! I've invited you to join the RxSwiftCommunity GitHub organization – no pressure to accept! If you'd like more information on what this means, check out our contributor guidelines and feel free to reach out with any questions.

Generated by :no_entry_sign: dangerJS